diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index d99ba82878c..7dd7b657708 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -47,14 +47,6 @@ jobs: with: install: true - - name: Cache Docker layers - uses: actions/cache@main - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-x86-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-x86- - - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: @@ -109,14 +101,6 @@ jobs: with: install: true - - name: Cache Docker layers - uses: actions/cache@main - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-arm-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-arm- - - name: Build uses: docker/build-push-action@v3.2.0 with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..d7727c8c99e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing to Canary + +Thank you for your interest in contributing to Canary! This document provides guidelines for contributing to the project to ensure a smooth and effective collaboration. + +## Code of Conduct + +This project adheres to the [Contributor Covenant Code of Conduct](https://github.com/opentibiabr/canary/blob/main/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at email: opentibiabr@outlook.com or discord: https://discord.com/invite/gvTj5sh9Mp + +## Project Roadmap + +- The Canary project is part of a larger ecosystem within the Open Tibia BR organization, which includes various projects focused on enhancing and innovating within OT server development. You can follow our shared roadmap, encompassing projects like Canary, OTServBR, and OTServBR-Global, among others, in the projects section on GitHub: [Open Tibia BR - Project Roadmap](https://github.com/orgs/opentibiabr/projects). + +- This roadmap aims to ensure alignment of initiatives and prioritize the development of improvements and new features that benefit the community. Community participation is crucial, and we encourage contributors to review the roadmap before proposing major changes, to ensure these align with the strategic direction of our projects. + + +## Getting Started + +### Issues + +- **Bug Reports**: If you encounter any bugs or issues while using Canary, please submit them via our [bug report template](https://github.com/opentibiabr/canary/blob/main/.github/ISSUE_TEMPLATE/bug.yaml). +- **Feature Requests**: If you have any ideas for features or enhancements, you can submit them through our [feature request template](https://github.com/opentibiabr/canary/blob/main/.github/ISSUE_TEMPLATE/request.yaml). + +Please provide as much relevant information as possible, including logs, screenshots, or other details to help the team understand the problem or your request. + +### Pull Requests + +To contribute code to the project, please follow these guidelines: + +1. **Fork the Repository**: Fork the Canary repository and create your own branch to make changes. +2. **Follow the Style Guides**: The project uses **Clang Format** for C++ and **Lua Format** for Lua scripts. It is important that your code follows these styles. We use GitHub Actions (GHA) for formatting checks, so make sure to format your code properly before submitting. +3. **No Complex Lua Scripts**: Contributions involving Lua scripts should focus on simple and efficient implementations. Performance-heavy features should be implemented in C++, and contributions that introduce overly complex Lua scripts may be rejected in favor of a C++ implementation. +4. **Database Standards**: We use an advanced key/value system for data storage called "KV System." We do not accept new tables in the MySQL database. All persistent data must be integrated using the KV system, which includes a protobuf-based abstraction for performance and integration. Please refer to the [KV System README](https://github.com/opentibiabr/canary/blob/main/src/kv/README.md) for more information. +5. **PR Guidelines**: Use our [Pull Request Template](https://github.com/opentibiabr/canary/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when submitting a pull request. Ensure your PR: + - Follows the project coding standards. + - Contains relevant descriptions and details about the changes. + - Respects project maintainers' decisions. Some contributions may not be merged immediately or might be rejected due to internal project priorities. +6. **Do Not Use Legacy Storage System**: Pull requests that introduce new features using the legacy storage system will not be accepted. Contributors must adopt the "KV System" to ensure compatibility with our modern approach. + +## Development Standards + +### Code Quality +- Follow modern C++20+ standards when contributing to the codebase. +- Ensure that your code is well-documented. Comments should be in English, and special attention should be given to areas that are hard to understand. + +### Formatting and Style +- **C++**: Code must be formatted with **Clang Format** according to the project's style configuration. +- **Lua**: Scripts must follow the formatting provided by **Lua Format**. + +We recommend using the provided GitHub Actions to validate the formatting before submitting any pull requests. + +## Communication + +Please use a respectful and welcoming tone when communicating with others. We aim to foster a positive and friendly community, so be mindful of others' perspectives and experiences. + +If you need to reach out to project maintainers for any assistance or inquiries, feel free to contact us at opentibiabr@outlook.com. + +## Review Process + +- Pull requests will be reviewed by the project maintainers. Please be patient, as it may take some time to get feedback. +- Contributors must be prepared for their PRs to be modified or even rejected. Reasons for this include internal priorities, a need for better performance, or violations of contribution guidelines. + +## Best Practices +- Respect the project standards and guidelines. +- Make small, focused pull requests, as it makes the review process easier. +- Write tests where possible to ensure that your changes do not introduce new issues. +- Provide clear descriptions in your commits and pull requests. +- Ensure that new features are properly integrated with existing systems. + +## Advanced Contribution +- **Complex Systems**: For features that impact performance or require deeper integrations, discuss them with the maintainers before implementation. +- **KV System Usage**: All persistent data should leverage the KV system. It allows for efficient data mapping, storing complex structures seamlessly. Learn more about the KV system [here](https://github.com/opentibiabr/canary/blob/main/src/kv/README.md). + +Thank you for your contributions and for helping make Canary better! + diff --git a/cmake/modules/CanaryLib.cmake b/cmake/modules/CanaryLib.cmake index 3e168d0569b..916970c37ea 100644 --- a/cmake/modules/CanaryLib.cmake +++ b/cmake/modules/CanaryLib.cmake @@ -62,6 +62,7 @@ target_include_directories(${PROJECT_NAME}_lib ${GMP_INCLUDE_DIRS} ${LUAJIT_INCLUDE_DIRS} ${PARALLEL_HASHMAP_INCLUDE_DIRS} + ${ATOMIC_QUEUE_INCLUDE_DIRS} ) # ***************************************************************************** diff --git a/data-canary/monster/bosses/apocalypse.lua b/data-canary/monster/bosses/apocalypse.lua index fba0ab1613a..47957c3ceab 100644 --- a/data-canary/monster/bosses/apocalypse.lua +++ b/data-canary/monster/bosses/apocalypse.lua @@ -143,18 +143,4 @@ monster.immunities = { { 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-canary/monster/bosses/apprentice_sheng.lua b/data-canary/monster/bosses/apprentice_sheng.lua index 5e16a274500..07eeb42917a 100644 --- a/data-canary/monster/bosses/apprentice_sheng.lua +++ b/data-canary/monster/bosses/apprentice_sheng.lua @@ -117,18 +117,4 @@ monster.immunities = { { 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-canary/monster/bosses/bazir.lua b/data-canary/monster/bosses/bazir.lua index 6c4a6eeccb5..353c392a3b0 100644 --- a/data-canary/monster/bosses/bazir.lua +++ b/data-canary/monster/bosses/bazir.lua @@ -179,18 +179,4 @@ monster.immunities = { { 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-canary/monster/bosses/black_knight.lua b/data-canary/monster/bosses/black_knight.lua index 1ca457b449e..fd9ff673ab4 100644 --- a/data-canary/monster/bosses/black_knight.lua +++ b/data-canary/monster/bosses/black_knight.lua @@ -126,18 +126,4 @@ monster.immunities = { { 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-canary/monster/bosses/bullwark.lua b/data-canary/monster/bosses/bullwark.lua index 7674d1dec01..1aa7974cfa0 100644 --- a/data-canary/monster/bosses/bullwark.lua +++ b/data-canary/monster/bosses/bullwark.lua @@ -124,18 +124,4 @@ monster.immunities = { { 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-canary/monster/bosses/custodian.lua b/data-canary/monster/bosses/custodian.lua index 21b9721d6a8..cf2d0c1fdf4 100644 --- a/data-canary/monster/bosses/custodian.lua +++ b/data-canary/monster/bosses/custodian.lua @@ -102,18 +102,4 @@ monster.immunities = { { 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-canary/monster/bosses/dharalion.lua b/data-canary/monster/bosses/dharalion.lua index 3f86d4a5269..3d3cb689684 100644 --- a/data-canary/monster/bosses/dharalion.lua +++ b/data-canary/monster/bosses/dharalion.lua @@ -132,18 +132,4 @@ monster.immunities = { { 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-canary/monster/bosses/shadowpelt.lua b/data-canary/monster/bosses/shadowpelt.lua index 16fb1e60256..dcae734c0d3 100644 --- a/data-canary/monster/bosses/shadowpelt.lua +++ b/data-canary/monster/bosses/shadowpelt.lua @@ -135,18 +135,4 @@ monster.immunities = { { 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-canary/scripts/actions/objects/imbuement_shrine.lua b/data-canary/scripts/actions/objects/imbuement_shrine.lua index 71e3776f2f0..11d75150cf8 100644 --- a/data-canary/scripts/actions/objects/imbuement_shrine.lua +++ b/data-canary/scripts/actions/objects/imbuement_shrine.lua @@ -13,5 +13,7 @@ function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotke return true end +imbuement:position({ x = 1943, y = 1340, z = 7 }, 25061) + imbuement:id(25060, 25061, 25103, 25104, 25202, 25174, 25175, 25182, 25183) imbuement:register() diff --git a/data-canary/scripts/actions/other/christmas_bundle.lua b/data-canary/scripts/actions/other/christmas_bundle.lua deleted file mode 100644 index 3c74fa30a4d..00000000000 --- a/data-canary/scripts/actions/other/christmas_bundle.lua +++ /dev/null @@ -1,72 +0,0 @@ -local setting = { -- [christmas bundle item id] = {{reward item id, count}, ...} - [6506] = { -- red bundle - { 6569, 15 }, -- candy - { 3585, 5 }, -- red apple - { 3586, 10 }, -- orange - { 3598, 20 }, -- cookie - { 3599, 10 }, -- candy cane - 6500, -- gingerbreadman - 6501, -- christmas wreath - 6489, -- christmas branch - 6503, -- red christmas garland - 6387, -- christmas card - }, - [6507] = { -- blue bundle - { 6569, 15 }, -- candy - { 3585, 5 }, -- red apple - { 3586, 10 }, -- orange - { 3598, 20 }, -- cookie - { 3599, 10 }, -- candy cane - 6500, -- gingerbreadman - 6501, -- christmas wreath - 6489, -- christmas branch - 6505, -- blue christmas garland - 6387, -- christmas card - }, - [6508] = { -- green bundle - { 6569, 15 }, -- candy - { 3585, 5 }, -- red apple - { 3586, 10 }, -- orange - { 3598, 20 }, -- cookie - { 3599, 10 }, -- candy cane - 6500, -- gingerbreadman - 6501, -- christmas wreath - 6489, -- christmas branch - 6502, -- christmas garland - 6387, -- christmas card - }, -} - -local christmasBundle = Action() - -function christmasBundle.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local targetItem = setting[item.itemid] - if not targetItem then - return true - end - - local rewards = {} - while #rewards < 7 do - local count = 1 - local rand = math.random(#targetItem) - local gift = targetItem[rand] - if type(gift) == "table" then - gift, count = unpack(gift) - end - rewards[#rewards + 1] = { gift, count } - table.remove(targetItem, rand) - end - - for i = 1, #rewards do - player:addItem(unpack(rewards[i])) - end - item:remove(1) - player:getPosition():sendMagicEffect(CONST_ME_GIFT_WRAPS) - return true -end - -for index, value in pairs(setting) do - christmasBundle:id(index) -end - -christmasBundle:register() diff --git a/data-canary/scripts/actions/other/destroy.lua b/data-canary/scripts/actions/other/destroy.lua index 587df2f5ea7..62af94ab101 100644 --- a/data-canary/scripts/actions/other/destroy.lua +++ b/data-canary/scripts/actions/other/destroy.lua @@ -250,7 +250,7 @@ local setting = { local destroy = Action() function destroy.onUse(player, item, fromPosition, target, toPosition, isHotkey) - return ActionsLib.destroyItem(player, target, toPosition) + return destroyItem(player, target, toPosition) end for index, value in ipairs(setting) do diff --git a/data-canary/scripts/actions/other/ferumbras_amulet.lua b/data-canary/scripts/actions/other/ferumbras_amulet.lua deleted file mode 100644 index 01f1ca7a502..00000000000 --- a/data-canary/scripts/actions/other/ferumbras_amulet.lua +++ /dev/null @@ -1,17 +0,0 @@ -local ferumbrasAmulet = Action() - -function ferumbrasAmulet.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if math.random(2) == 1 then - player:addMana(1000) - else - player:addHealth(1000) - end - item:transform(22768) - item:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED) - item:decay() - player:say("Magical sparks whirl around the amulet and you suddenly feel refreshed.", TALKTYPE_MONSTER_SAY) - return true -end - -ferumbrasAmulet:id(22767) -ferumbrasAmulet:register() diff --git a/data-canary/scripts/actions/other/ferumbras_mana_keg.lua b/data-canary/scripts/actions/other/ferumbras_mana_keg.lua deleted file mode 100644 index c1400379d6d..00000000000 --- a/data-canary/scripts/actions/other/ferumbras_mana_keg.lua +++ /dev/null @@ -1,13 +0,0 @@ -local ferumbrasManaKeg = Action() - -function ferumbrasManaKeg.onUse(player, item, fromPosition, target, toPosition, isHotkey) - player:addItem(238, 10) - item:transform(22770) - item:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED) - item:decay() - player:say("Magical sparks whirl around the keg as you open the spigot and you fill ten empty vials with mana fluid.", TALKTYPE_MONSTER_SAY) - return true -end - -ferumbrasManaKeg:id(22769) -ferumbrasManaKeg:register() diff --git a/data-canary/scripts/actions/other/ferumbras_staff.lua b/data-canary/scripts/actions/other/ferumbras_staff.lua deleted file mode 100644 index f2f897f2c3f..00000000000 --- a/data-canary/scripts/actions/other/ferumbras_staff.lua +++ /dev/null @@ -1,16 +0,0 @@ -local ferumbrasStaff = Action() - -function ferumbrasStaff.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if math.random(100) > 20 then - item:transform(22767) - else - item:transform(22766) - end - item:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED) - item:decay() - player:say("Magical sparks whirl around the staff and suddenly it changes its appearance.", TALKTYPE_MONSTER_SAY) - return ActionsLib.destroyItem(player, target, toPosition) -end - -ferumbrasStaff:id(22764) -ferumbrasStaff:register() diff --git a/data-canary/scripts/actions/other/music.lua b/data-canary/scripts/actions/other/music.lua index eb44c56aeed..589723a1f89 100644 --- a/data-canary/scripts/actions/other/music.lua +++ b/data-canary/scripts/actions/other/music.lua @@ -27,8 +27,6 @@ local setting = { [2966] = { effect = CONST_ME_SOUND_RED }, -- war drum [3103] = { effect = CONST_ME_SOUND_YELLOW, itemId = 3592, itemCount = 10, chance = 80, remove = true }, -- cornucopia [5786] = { effects = { failure = CONST_ME_SOUND_RED, success = CONST_ME_SOUND_YELLOW }, monster = "war wolf", chance = 60, remove = true }, -- wooden whistle - [6572] = { effect = CONST_ME_SOUND_GREEN, text = "TOOOOOOT", transformId = 6573, decayId = 6572 }, -- party trumpet - [6573] = { effect = CONST_ME_SOUND_GREEN, text = "TOOOOOOT", transformId = 6572, decayId = 6573 }, -- party trumpet [12602] = { effect = CONST_ME_SOUND_BLUE }, -- small whistle (actual effect is unknown) [23725] = { effect = CONST_ME_SOUND_WHITE }, -- small crystal bell } diff --git a/data-canary/scripts/actions/other/sewer.lua b/data-canary/scripts/actions/other/sewer.lua deleted file mode 100644 index 2868e887ae5..00000000000 --- a/data-canary/scripts/actions/other/sewer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local sewer = Action() - -function sewer.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item:getId() == 435 then - fromPosition.z = fromPosition.z + 1 - end - player:teleportTo(fromPosition, false) - return true -end - -sewer:id(435) -sewer:register() diff --git a/data-canary/scripts/actions/other/surprise_bag.lua b/data-canary/scripts/actions/other/surprise_bag.lua deleted file mode 100644 index be59af96267..00000000000 --- a/data-canary/scripts/actions/other/surprise_bag.lua +++ /dev/null @@ -1,62 +0,0 @@ -local setting = { - -- Blue present - [6570] = { - { 3598, 10 }, - { 6393, 3 }, - 2995, - 6569, - 6572, - 6574, - 6575, - 6576, - 6577, - 6578, - 6279, - }, - -- Red present - [6571] = { - { 3035, 10 }, - { 3035, 10 }, - { 3035, 10 }, - { 2995, 3 }, - { 6392, 2 }, - { 6574, 2 }, - { 6576, 2 }, - { 6578, 2 }, - 2993, - 3036, - 3079, - 3386, - 3420, - 5944, - 6566, - 6568, - }, -} - -local surpriseBag = Action() - -function surpriseBag.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local count = 1 - local targetItem = setting[item.itemid] - if not targetItem then - return true - end - - local gift = targetItem[math.random(#targetItem)] - if type(gift) == "table" then - gift = gift[1] - count = gift[2] - end - - player:addItem(gift, count) - item:remove(1) - fromPosition:sendMagicEffect(CONST_ME_GIFT_WRAPS) - return true -end - -for index, value in pairs(setting) do - surpriseBag:id(index) -end - -surpriseBag:register() diff --git a/data-canary/scripts/creaturescripts/#modal_window_example.lua b/data-canary/scripts/creaturescripts/#modal_window_example.lua deleted file mode 100644 index e2de4a9e474..00000000000 --- a/data-canary/scripts/creaturescripts/#modal_window_example.lua +++ /dev/null @@ -1,63 +0,0 @@ ---[[ - ModalWindowHelper Example -]] --- - -local moveDirectionTest = { - ["Right"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_EAST) - player:teleportTo(pos, true) - end, - ["Left"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_WEST) - player:teleportTo(pos, true) - end, - ["Up"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_NORTH) - player:teleportTo(pos, true) - end, - ["Down"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_SOUTH) - player:teleportTo(pos, true) - end, -} - -local talkAction = TalkAction("!modalTest") - -function talkAction.onSay(player, words, param, type) - local modalWindow = ModalWindow({ - title = "Modal Window Helper Example", - message = "This is an example of ModalWindowHelper.", - }) - if param == "choices" then - for text, callback in pairs(moveDirectionTest) do - modalWindow:addChoice(text, function(player, button, choice) - if button.name == "Select" then - callback(player) - modalWindow:sendToPlayer(player) - end - end) - end - - modalWindow:addButton("Select") - modalWindow:addButton("Cancel") - elseif param == "buttons" then - for direction, callback in pairs(moveDirectionTest) do - modalWindow:addButton(direction, function(player, button, choice) - callback(player) - modalWindow:sendToPlayer(player) - end) - end - end - modalWindow:sendToPlayer(player) - return false -end - ---talkAction:accountType(ACCOUNT_TYPE_GOD) ---talkAction:access(true) -talkAction:separator(" ") -talkAction:register() diff --git a/data-canary/scripts/creaturescripts/monster.lua b/data-canary/scripts/creaturescripts/monster.lua deleted file mode 100644 index abbdae1aea4..00000000000 --- a/data-canary/scripts/creaturescripts/monster.lua +++ /dev/null @@ -1,24 +0,0 @@ -local monsterDeath = CreatureEvent("monsterDeath") -function monsterDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if creature:isMonster() then - local self = creature:getStorageValue(MonsterStorage.Spawn.monster_spawn_object) - self:executeFunctionMonster("onDeath", creature) - self:deleteMonster(creature) - return true - end - return true -end - -local monsterDeathBoss = CreatureEvent("monsterDeathBoss") -function monsterDeathBoss.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if creature:isMonster() then - local self = creature:getStorageValue(MonsterStorage.Spawn.monster_spawn_object) - self:removeSpawn() - self:removeMonsters() - return true - end - return true -end - -monsterDeathBoss:register() -monsterDeath:register() diff --git a/data-otservbr-global/lib/core/quests.lua b/data-otservbr-global/lib/core/quests.lua index 8d7d9ede37c..19b5a058986 100644 --- a/data-otservbr-global/lib/core/quests.lua +++ b/data-otservbr-global/lib/core/quests.lua @@ -5169,12 +5169,12 @@ if not Quests then }, [36] = { name = "Forgotten Knowledge", - startStorageId = Storage.ForgottenKnowledge.Tomes, + startStorageId = Storage.Quest.U11_02.ForgottenKnowledge.Tomes, startStorageValue = 1, missions = { [1] = { name = "Circle of the Black Sphinx", - storageId = Storage.ForgottenKnowledge.LadyTenebrisKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.LadyTenebrisKilled, missionId = 10361, startValue = 0, endValue = 1522018605, @@ -5184,7 +5184,7 @@ if not Quests then }, [2] = { name = "Bane of the Cosmic Force", - storageId = Storage.ForgottenKnowledge.LloydKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.LloydKilled, missionId = 10362, startValue = 0, endValue = 1522018605, @@ -5195,7 +5195,7 @@ if not Quests then }, [3] = { name = "The Desecrated Glade", - storageId = Storage.ForgottenKnowledge.ThornKnightKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.ThornKnightKilled, missionId = 10363, startValue = 0, endValue = 1522018605, @@ -5206,7 +5206,7 @@ if not Quests then }, [4] = { name = "The Unwary Mage", - storageId = Storage.ForgottenKnowledge.DragonkingKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.DragonkingKilled, missionId = 10364, startValue = 0, endValue = 1522018605, @@ -5217,7 +5217,7 @@ if not Quests then }, [5] = { name = "Dragon in Distress", - storageId = Storage.ForgottenKnowledge.HorrorKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.HorrorKilled, missionId = 10365, startValue = 0, endValue = 1522018605, @@ -5227,7 +5227,7 @@ if not Quests then }, [6] = { name = "Time is a Window", - storageId = Storage.ForgottenKnowledge.TimeGuardianKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled, missionId = 10366, startValue = 0, endValue = 1522018605, @@ -5238,7 +5238,7 @@ if not Quests then }, [7] = { name = "Final Fight", - storageId = Storage.ForgottenKnowledge.LastLoreKilled, + storageId = Storage.Quest.U11_02.ForgottenKnowledge.LastLoreKilled, missionId = 10367, startValue = 0, endValue = 1522018605, @@ -5250,22 +5250,22 @@ if not Quests then }, [37] = { name = "The First Dragon", - startStorageId = Storage.FirstDragon.Questline, + startStorageId = Storage.Quest.U11_02.TheFirstDragon.Questline, startStorageValue = 1, missions = { [1] = { name = "Power", - storageId = Storage.FirstDragon.DragonCounter, + storageId = Storage.Quest.U11_02.TheFirstDragon.DragonCounter, missionId = 10368, startValue = 0, endValue = 200, description = function(player) - return ("You already hunted %d/200 dragons."):format(player:getStorageValue(Storage.FirstDragon.DragonCounter)) + return ("You already hunted %d/200 dragons."):format(player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.DragonCounter)) end, }, [2] = { name = "Treasure", - storageId = Storage.FirstDragon.ChestCounter, + storageId = Storage.Quest.U11_02.TheFirstDragon.ChestCounter, missionId = 10369, startValue = 0, endValue = 20, @@ -5274,7 +5274,7 @@ if not Quests then }, [3] = { name = "Knowledge", - storageId = Storage.FirstDragon.GelidrazahAccess, + storageId = Storage.Quest.U11_02.TheFirstDragon.GelidrazahAccess, missionId = 10370, startValue = 0, endValue = 1, @@ -5283,7 +5283,7 @@ if not Quests then }, [4] = { name = "Life", - storageId = Storage.FirstDragon.SecretsCounter, + storageId = Storage.Quest.U11_02.TheFirstDragon.SecretsCounter, missionId = 10371, startValue = 0, endValue = 3, @@ -5294,23 +5294,23 @@ if not Quests then }, [38] = { name = "Cults of Tibia", - startStorageId = Storage.CultsOfTibia.Questline, + startStorageId = Storage.Quest.U11_40.CultsOfTibia.Questline, startStorageValue = 1, missions = { [1] = { name = "The Strengthtening of the Minotaurs", - storageId = Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, + storageId = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask, missionId = 10372, startValue = 0, endValue = 50, description = function(player) return ("James asked you to enter the cave for hunting 50 empowered minotaurs. \z - Then he will be able to continue his research.\nMinotaurs killed: %d/50"):format(player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask)) + Then he will be able to continue his research.\nMinotaurs killed: %d/50"):format(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask)) end, }, [2] = { name = "The Strengthtening of the Minotaurs", - storageId = Storage.CultsOfTibia.Minotaurs.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, missionId = 10373, startValue = 1, endValue = 5, @@ -5326,7 +5326,7 @@ if not Quests then }, [3] = { name = "Patron of Arts", - storageId = Storage.CultsOfTibia.MotA.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, missionId = 10374, startValue = 1, endValue = 15, @@ -5359,7 +5359,7 @@ if not Quests then }, [4] = { name = "Barkless", - storageId = Storage.CultsOfTibia.Barkless.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, missionId = 10375, startValue = 1, endValue = 7, @@ -5371,7 +5371,7 @@ if not Quests then The hardest part, however, is yet to come. Give your life to the ice... to become true and purified.", [3] = function(player) return ("You survived the Trial. Barkless now have the right to see the cult leader but a \z - powerful relic is sealing the path. Barkless markings broken to reverse the power of the cult object: \z %d of 10"):format(math.max(player:getStorageValue(Storage.CultsOfTibia.Barkless.Objects), 0)) + powerful relic is sealing the path. Barkless markings broken to reverse the power of the cult object: \z %d of 10"):format(math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects), 0)) end, [4] = "You broke enough Barkless markings to now reverse the seal \z held up by the cult object in the ritual chamber. \z @@ -5387,7 +5387,7 @@ if not Quests then }, [5] = { name = "Misguided", - storageId = Storage.CultsOfTibia.Misguided.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, missionId = 10376, startValue = 1, endValue = 5, @@ -5397,7 +5397,7 @@ if not Quests then hinted at something weird going on in a cave. He seemed too confused to decide whether to stop you.", [3] = function(player) return ("While rubbish, the amulet you equipe emits a strange aura of splendour. \z - You feel an urge to fulfill the amulets hunger for especific deaths... Exorcisms: %d/5 "):format(math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms), 0)) + You feel an urge to fulfill the amulets hunger for especific deaths... Exorcisms: %d/5 "):format(math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Exorcisms), 0)) end, [4] = "You defeated the cult leader of Misguided by uncovering the true master to pull his strings \z and freeing this world from its malicious existance. Return to Gerimor to tell him about the victory.", @@ -5406,7 +5406,7 @@ if not Quests then }, [6] = { name = "The Orc Idol", - storageId = Storage.CultsOfTibia.Orcs.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Orcs.Mission, missionId = 10377, startValue = 1, endValue = 3, @@ -5420,7 +5420,7 @@ if not Quests then }, [7] = { name = "The Secret of the Sandy Cave", - storageId = Storage.CultsOfTibia.Life.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Life.Mission, missionId = 10378, startValue = 1, endValue = 10, @@ -5445,7 +5445,7 @@ if not Quests then }, [8] = { name = "Zathroth Remmants", - storageId = Storage.CultsOfTibia.Humans.Mission, + storageId = Storage.Quest.U11_40.CultsOfTibia.Humans.Mission, missionId = 10379, startValue = 1, endValue = 3, @@ -5463,12 +5463,12 @@ if not Quests then }, [39] = { name = "Dangerous Depths", - startStorageId = Storage.DangerousDepths.Questline, + startStorageId = Storage.Quest.U11_50.DangerousDepths.Questline, startStorageValue = 1, missions = { [1] = { name = "Dwarves: Home Improvement", - storageId = Storage.DangerousDepths.Dwarves.Home, + storageId = Storage.Quest.U11_50.DangerousDepths.Dwarves.Home, missionId = 10380, startValue = 1, endValue = 2, @@ -5476,14 +5476,14 @@ if not Quests then [1] = function(player) return ("Destroy makeshift homes of the Lost to force them to fight you! Try making some \z prisoners in the progress and report back to Klom Stonecutter.\n\nLost Exiles: %d/20\nPrisoners (bonus): \z - %d/3"):format(math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles), 0), math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners), 0)) + %d/3"):format(math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles), 0), math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners), 0)) end, [2] = "You drove off the Lost but more are sure to come. Check back with Klom Stonecutter at a later time.", }, }, [2] = { name = "Dwarves: Subterranean Life", - storageId = Storage.DangerousDepths.Dwarves.Subterranean, + storageId = Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean, missionId = 10381, startValue = 1, endValue = 2, @@ -5491,7 +5491,7 @@ if not Quests then [1] = function(player) return ("Klome Stonecutter sent you on a grave mission to exterminate large populaces of \z subterranian life. Looks like the dwarves make short work of the deep intruders.\n\nSubterranean organisms: \z - %d/50"):format(math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms), 0)) + %d/50"):format(math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms), 0)) end, [2] = "You helped Klom defend the outpost by cutting down a number of vermin from deep down below. \z The gnomes don't seem to completely approve of this but everyone appreciates the drop in the enemy's ranks.", @@ -5499,7 +5499,7 @@ if not Quests then }, [3] = { name = "Gnomes: Gnomal Warming Measurements", - storageId = Storage.DangerousDepths.Gnomes.Measurements, + storageId = Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements, missionId = 10382, startValue = 1, endValue = 2, @@ -5507,11 +5507,11 @@ if not Quests then [1] = function(player) return ("Gnomus sent you on a mission to measure the rising heat from below.\n\nLocation A: \z %d/1\nLocation B: %d/1\nLocation C: %d/1\nLocation D: %d/1\nLocation E: %d/1"):format( - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationA), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationB), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationC), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationD), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationE), 0) + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationA), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationB), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationC), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationD), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationE), 0) ) end, [2] = "You helped Lardoc Bashsmite fighting back the verminous growth in the northern mineshaft. \z @@ -5520,7 +5520,7 @@ if not Quests then }, [4] = { name = "Gnomes: Ordnance", - storageId = Storage.DangerousDepths.Gnomes.Ordnance, + storageId = Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, missionId = 10383, startValue = 1, endValue = 3, @@ -5529,7 +5529,7 @@ if not Quests then Travel to the east of the cave system and find the old gnome trail where reinforcements will arrive.", [2] = function(player) return ("You found the old gnome trail where ordnance for the gnome outpost arrive, escort them \z - and their pack animals to safety and return to Gnomus.\n\nRescued gnomes: %d/5\nRescued animals: %d/3"):format(math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount), 0), math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount), 0)) + and their pack animals to safety and return to Gnomus.\n\nRescued gnomes: %d/5\nRescued animals: %d/3"):format(math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount), 0), math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount), 0)) end, [3] = "You helped Lardoc Bashsmite fighting back the verminous growth in the northern mineshaft. \z Return to him later to see if he has more work for you.", @@ -5537,7 +5537,7 @@ if not Quests then }, [5] = { name = "Gnomes: Uncharted Territory", - storageId = Storage.DangerousDepths.Gnomes.Charting, + storageId = Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting, missionId = 10384, startValue = 1, endValue = 2, @@ -5546,12 +5546,12 @@ if not Quests then return ("Chart the area around the deep base for Gnomus. Look for especific landmarks: \z \n\nOld Gate: %d/1\nThe Gaze: %d/1\nLost Ruin: %d/1\nOutpost: %d/1\nBastion: %d/1\nBroken Tower: \z %d/1"):format( - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.OldGate), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.TheGaze), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.LostRuin), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.Outpost), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.Bastion), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.BrokenTower), 0) + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.OldGate), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TheGaze), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LostRuin), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Outpost), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Bastion), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.BrokenTower), 0) ) end, [2] = "You helped Gnomus chart the area around the deep base. You found traces of what \z @@ -5560,7 +5560,7 @@ if not Quests then }, [6] = { name = "Scouts: Explosive Growth", - storageId = Storage.DangerousDepths.Scouts.Growth, + storageId = Storage.Quest.U11_50.DangerousDepths.Scouts.Growth, missionId = 10385, startValue = 1, endValue = 2, @@ -5568,11 +5568,11 @@ if not Quests then [1] = function(player) return ("You found the mine shaft. Burn all the growth and report back to Lardoc Bashsmite! \z \n\nFirst Room: %d/1\nSecond room: %d/1\nThird room: %d/1\nFourth room: %d/1\nFifth room: %d/1"):format( - math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.FirstBarrel), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.SecondBarrel), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.ThirdBarrel), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.FourthBarrel), 0), - math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.FifthBarrel), 0) + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FirstBarrel), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.SecondBarrel), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.ThirdBarrel), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FourthBarrel), 0), + math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FifthBarrel), 0) ) end, [2] = "You helped Lardoc Bashsmite fighting back the verminous growth in the northern mineshaft. \z @@ -5581,7 +5581,7 @@ if not Quests then }, [7] = { name = "Scouts: Pesticide", - storageId = Storage.DangerousDepths.Scouts.Diremaw, + storageId = Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw, missionId = 10386, startValue = 1, endValue = 2, @@ -5589,7 +5589,7 @@ if not Quests then [1] = function(player) return ("Lardoc asked you to follow a plan of the gnomes to stop the deep threat by trying to \z neutralise diremaw spawn with pesticies. Diremaws lay eggs inside corpses of their skin. \z - \n\nNeutralised: %d/20"):format(math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount), 0)) + \n\nNeutralised: %d/20"):format(math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount), 0)) end, [2] = "You reported back to Lardoc Bashsmite to inform him that the gnome's plan to \z neutralise diremaw corpses seems to work.", @@ -6533,5 +6533,105 @@ if not Quests then }, }, }, + [49] = { + name = "The Secret Library", + startStorageId = Storage.Quest.U11_80.TheSecretLibrary.Questlog, + startStorageValue = 1, + missions = { + [1] = { + name = "High and Dry", + storageId = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, + missionId = 10451, + startValue = 1, + endValue = 4, + states = { + [1] = "Dedoras asked for you to talk to Charles, he knows about a small island.", + [2] = "You got stucked on this island. You must discover how to leave.", + [3] = "You successfully built a raft and used the starts to navigate your way through the waves. At least you found something of interest on the deserted island.", + [4] = "Congratulations you completed this mission.", + }, + }, + [2] = { + name = "Liquid Death", + storageId = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, + missionId = 10452, + startValue = 1, + endValue = 8, + states = { + [1] = "Dedoras has sent you to Spectulus in the Edron Academy. Rumors of strange fishmen in the Tiquanda region may be connected to some of the research the scholar conducted.", + [2] = "Spectulus asked you to check out the rumors of strange fishmen in the jungles of northern Tiquanda. A small sunken temple is said to be overrun by strange fish-like creatures.", + [3] = "You found a sunken temple deep in the Tiquanda jungle. Spectulus will help you enter the vortex at the entrance. Find out what happened there and take care of the fish-like aggressors...", + [4] = "Part IV", + [5] = "Part V", + [6] = "Part VI", + [7] = "Brokul has been defeated and now you can talk with Spectulus or Dedoras what you found about the fishmen.", + [8] = "Congratulations you completed this mission.", + }, + }, + [3] = { + name = "Asuri - The Lament", + storageId = Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, + missionId = 10453, + startValue = 1, + endValue = 7, + states = { + [1] = "Go to Asuri Palace in Port Hope.", + [2] = "You were able to assemble an instrument with the objects found. That should work for something.", + [3] = "You must talk with the dead girl's mother, Gail, at Port Hope.", + [4] = "With a heavy heart you used a piece of ebony as well as the skull and hair of an unfortunate maiden to create a bone fiddle. By playing the Peacock Ballad you should be able to open the viollet portal.", + [5] = "You may enter the viollet portal. Check if there is something useful there.", + [6] = "In a secret room of the Asura Palace you discovered an old writing desk that contains an ancient map. This must be a hint to the secret library you are searching for.", + [7] = "Congratulations you completed this mission.", + }, + }, + [4] = { + name = "The Order of the Falcon", + storageId = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline, + missionId = 10454, + startValue = 1, + endValue = 3, + states = { + [1] = "It is said that an ancient order of knights once resided in Edron. The knights disappeared a long time ago but their abandoned outpost is still there. The place may yet hold some surprises.", + [2] = "You defeated Grand Master Oberon in mortal combat. The Falcon Order may have lost its glory a long time ago but you are just getting started.", + [3] = "Congratulations you completed this mission.", + }, + }, + [5] = { + name = "The Path of Defiances", + storageId = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, + missionId = 10455, + startValue = 1, + endValue = 9, + states = { + [1] = "Go to Darashia and find out about the mysterious statue.", + [2] = "After you have been swallowed by a sand vortex you have entered a hidden desert area. A voice of unknown origin has informed you that you will have to face some challenges.", + [3] = "Part III", + [4] = "Part IV", + [5] = "Part V", + [6] = "Part VI", + [7] = "Part VII", + [8] = "You have found a book page in a chest. It seems to contain very useful information, but you are not capable to read it. At this point you have to speak with an expert.", + [9] = "Congratulations you completed this mission.", + }, + }, + [6] = { + name = "Bursting at the Seams", + storageId = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, + missionId = 10456, + startValue = 1, + endValue = 8, + states = { + [1] = "Dedoras told you where to search for leads to the Veiled Hoard: the museum in Thais, a fishmen temple in Tiquanda, an order fortress in Edron, the Asuri Palace and a deserted isle.", + [2] = "You talked with Gareth and now you may pass trougth the door.", + [3] = "Part III", + [4] = "Part IV", + [5] = "Part V", + [6] = "You successfully entered the Veiled Hoard of Zathroth. However, countless secret and vast knowledge still lie ahead.", + [7] = "You have reported Gareth about the enigmatic inscription you have found in the chamber of doom. He was able to decipher it for you and referred to Dedoras in Cormaya for further assistance.", + [8] = "Congratulations you completed this mission.", + }, + }, + }, + }, } end diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua index 1c4033b09bc..4529c64f583 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -187,39 +187,6 @@ Storage = { AccessDoor = 50043, CatacombDoors = 55047, }, - TheSecretLibrary = { - -- Reserved storage from 50050 - 50074 - TheOrderOfTheFalcon = { - OberonTimer = 50050, - }, - LiquidDeath = 50051, - Mota = 50052, - MotaDoor = 50053, - BasinDoor = 50054, - SkullDoor = 50055, - TheLament = 50056, - GreenTel = 50057, - BlueTel = 50058, - BlackTel = 50059, - PinkTel = 50060, - Peacock = 50061, - HighDry = 50062, - FalconBastionAccess = 50063, - FalconBastionChestsTimer = { - Key0909 = 50064, - }, - MiniBosses = { - GrandCommanderSoeren = 50065, - PreceptorLazare = 50066, - GrandChaplainGaunder = 50067, - GrandCanonDominus = 50068, - DazedLeafGolem = 50069, - }, - LowerBastionAccess = 50070, - UndergroundBastionAccess = 50071, - OberonAccess = 50072, - ShortcutToBastion = 50073, - }, DeeplingBosses = { -- Reserved storage from 50075 - 50079 Jaul = 50075, @@ -227,193 +194,6 @@ Storage = { Obujos = 50077, DeeplingStatus = 50078, }, - DangerousDepths = { - -- Reserved storage from 50080 - 50199 - Questline = 50080, - Dwarves = { - Status = 50081, - Home = 50082, -- Mission - Subterranean = 50083, -- Mission - LostExiles = 50084, - Prisoners = 50085, - Organisms = 50086, - TimeTaskHome = 50087, - TimeTaskSubterranean = 50088, - }, - Scouts = { - Status = 50090, - Diremaw = 50091, -- Mission - Growth = 50092, -- Mission - DiremawsCount = 50093, - GnomishChest = 50094, - BarrelCount = 50095, - FirstBarrel = 50096, - SecondBarrel = 50097, - ThirdBarrel = 50098, - FourthBarrel = 50099, - FifthBarrel = 50100, - TimeTaskDiremaws = 50101, - TimeTaskGrowth = 50102, - Barrel = 50103, - BarrelTimer = 50104, - }, - Gnomes = { - Status = 50115, - Ordnance = 50116, -- Mission - Measurements = 50117, -- Mission - Charting = 50118, -- Mission - GnomeChartChest = 50119, -- Measurements - GnomeChartPaper = 50120, -- Charting - GnomesCount = 50121, -- Ordnance - CrawlersCount = 50122, -- Ordnance - LocationA = 50123, -- Measurements - LocationB = 50124, -- Measurements - LocationC = 50125, -- Measurements - LocationD = 50126, -- Measurements - LocationE = 50127, -- Measurements - LocationCount = 50128, -- Measurements - OldGate = 50129, -- Charting - TheGaze = 50130, -- Charting - LostRuin = 50131, -- Charting - Outpost = 50132, -- Charting - Bastion = 50133, - -- Charting - BrokenTower = 50134, -- Charting - ChartingCount = 50135, -- Contador - TimeTaskOrdnance = 50136, - TimeTaskMeasurements = 50137, - TimeTaskCharting = 50138, - }, - Access = { - LavaPumpWarzoneVI = 50139, - TimerWarzoneVI = 50140, - LavaPumpWarzoneV = 50141, - TimerWarzoneV = 50142, - LavaPumpWarzoneIV = 50143, - TimerWarzoneIV = 50144, - }, - Crystals = { - WarzoneVI = { - BigCrystal1 = 50155, - BigCrystal2 = 50156, - MediumCrystal1 = 50157, - MediumCrystal2 = 50158, - SmallCrystal1 = 50159, - SmallCrystal2 = 50160, - }, - WarzoneV = { - BigCrystal1 = 50165, - BigCrystal2 = 50166, - MediumCrystal1 = 50167, - MediumCrystal2 = 50168, - SmallCrystal1 = 50169, - SmallCrystal2 = 50170, - }, - WarzoneIV = { - BigCrystal1 = 50175, - BigCrystal2 = 50176, - MediumCrystal1 = 50177, - MediumCrystal2 = 50178, - SmallCrystal1 = 50179, - SmallCrystal2 = 50180, - }, - }, - Bosses = { - TheCountOfTheCore = 50185, - TheDukeOfTheDepths = 50186, - TheBaronFromBelow = 50187, - TheCountOfTheCoreAchiev = 50188, - TheDukeOfTheDepthsAchiev = 50189, - TheBaronFromBelowAchiev = 50190, - LastAchievement = 50191, - }, - }, - CultsOfTibia = { - -- Reserved storage from 50200 - 50269 - Questline = 50200, - Minotaurs = { - EntranceAccessDoor = 50201, - JamesfrancisTask = 50202, - Mission = 50203, - BossTimer = 50204, - AccessDoor = 50205, - }, - MotA = { - Mission = 50210, - Stone1 = 50211, - Stone2 = 50212, - Stone3 = 50213, - Answer = 50214, - QuestionId = 50215, - AccessDoorInvestigation = 50216, - AccessDoorGareth = 50217, - AccessDoorDenominator = 50218, - }, - Barkless = { - Mission = 50225, - sulphur = 50226, - Tar = 50227, - Ice = 50228, - Death = 50229, - Objects = 50230, - Temp = 50231, - BossTimer = 50232, - TrialAccessDoor = 50243, -- 50233 is used by an ore wagon - TarAccessDoor = 50234, - AccessDoor = 50235, - BossAccessDoor = 50236, - }, - Orcs = { - Mission = 50240, - LookType = 50241, - BossTimer = 50242, - }, - Life = { - Mission = 50245, - BossTimer = 50246, - AccessDoor = 50264, - }, - Humans = { - Mission = 50250, - Vaporized = 50251, - Decaying = 50252, - BossTimer = 50253, - }, - Misguided = { - Mission = 50255, - Monsters = 50256, - Exorcisms = 50257, - Time = 50258, - BossTimer = 50259, - AccessDoor = 50260, - }, - FinalBoss = { - Mission = 50261, - BossTimer = 50262, - AccessDoor = 50263, - }, - }, - FirstDragon = { - -- Reserved storage from 50350 - 50379 - Questline = 50350, - DragonCounter = 50351, - ChestCounter = 50352, - SecretsCounter = 50355, - GelidrazahAccess = 50356, - DesertTile = 50358, - StoneSculptureTile = 50359, - SuntowerTile = 50360, - Horn = 50362, - Scale = 50363, - Bones = 50364, - Tooth = 50365, - AccessCave = 50366, - SomewhatBeatable = 50367, - FirstDragonTimer = 50368, - RewardFeather = 50369, - RewardMask = 50370, - RewardBackpack = 50371, - }, HeroRathleton = { -- Reserved storage from 50400 - 50419 QuestLine = 50400, @@ -424,41 +204,6 @@ Storage = { AccessTeleport2 = 50405, AccessTeleport3 = 50406, }, - ForgottenKnowledge = { - -- Reserved storage from 50470 - 50519 - AccessDeath = 50470, - AccessViolet = 50471, - AccessEarth = 50472, - AccessFire = 50473, - AccessIce = 50474, - AccessGolden = 50475, - AccessLast = 50476, - OldDesk = 50477, - GirlPicture = 50478, - SilverKey = 50479, - Phial = 50480, - BirdCounter = 50481, - PlantCounter = 50482, - GoldenServantCounter = 50483, - DiamondServantCounter = 50484, - AccessPortals = 50485, - AccessMachine = 50486, - LadyTenebrisKilled = 50488, - LloydKilled = 50490, - ThornKnightKilled = 50492, - DragonkingKilled = 50494, - HorrorKilled = 50496, - TimeGuardianKilled = 50498, - LastLoreKilled = 50501, - BirdCage = 50502, - AccessLavaTeleport = 50503, - Ivalisse = 50504, - Chalice = 50505, - Tomes = 50506, - BabyDragon = 50507, - SpiderWeb = 50508, - LloydEvent = 50509, - }, SweetyCyclops = { -- Reserved storage from 50520 - 50529 AmuletTimer = 50520, @@ -2522,12 +2267,140 @@ Storage = { HeartOfDestruction = {}, }, U11_02 = { -- update 11.02 - Reserved Storages 45451 - 45650 - FestiveOutfits = {}, - FirstDragon = {}, - ForgottenKnowledge = {}, + FestiveOutfits = { + Addon1 = 45451, + Addon2 = 45452, + }, + TheFirstDragon = { + Questline = 45453, + DragonCounter = 45454, + ChestCounter = 45455, + SecretsCounter = 45456, + GelidrazahAccess = 45457, + DesertTile = 45458, + StoneSculptureTile = 45459, + SuntowerTile = 45460, + Horn = 45461, + Scale = 45462, + Bones = 45463, + Tooth = 45464, + AccessCave = 45465, + SomewhatBeatable = 45466, + FirstDragonTimer = 45467, + RewardFeather = 45468, + RewardMask = 45469, + RewardBackpack = 45470, + Feathers = 45471, + }, + ForgottenKnowledge = { + AccessDeath = 45472, + AccessViolet = 45473, + AccessEarth = 45474, + AccessFire = 45475, + AccessIce = 45476, + AccessGolden = 45477, + AccessLast = 45478, + OldDesk = 45479, + GirlPicture = 45480, + SilverKey = 45481, + Phial = 45482, + BirdCounter = 45483, + PlantCounter = 45484, + GoldenServantCounter = 45485, + DiamondServantCounter = 45486, + AccessPortals = 45487, + AccessMachine = 45488, + LadyTenebrisKilled = 45489, + LloydKilled = 45490, + ThornKnightKilled = 45491, + DragonkingKilled = 45492, + HorrorKilled = 45493, + TimeGuardianKilled = 45494, + LastLoreKilled = 45495, + BirdCage = 45496, + AccessLavaTeleport = 45497, + Ivalisse = 45498, + Chalice = 45499, + Tomes = 45500, + BabyDragon = 45501, + SpiderWeb = 45502, + LloydEvent = 45503, + ActiveTree = 45504, + MechanismGolden = 45505, + MechanismDiamond = 45506, + GoldenServant = 45507, + DiamondServant = 45508, + AstralPowerCounter = 45509, + AstralGlyph = 45510, + }, }, U11_40 = { -- update 11.40 - Reserved Storages 45651 - 45850 - CultsOfTibia = {}, -- 45651 - 45750 + CultsOfTibia = { -- 45651 - 45750 + Questline = 45651, + Minotaurs = { + BossAccessDoor = 45652, + JamesfrancisTask = 45653, + Mission = 45654, + BossTimer = 45655, + AccessDoor = 45656, + }, + MotA = { + Mission = 45657, + Stone1 = 45658, + Stone2 = 45659, + Stone3 = 45660, + Answer = 45661, + QuestionId = 45662, + AccessDoorInvestigation = 45663, + AccessDoorGareth = 45664, + AccessDoorDenominator = 45665, + }, + Barkless = { + Mission = 45666, + Sulphur = 45667, + Tar = 45668, + Ice = 45669, + Death = 45670, + Objects = 45671, + Temp = 45672, + BossTimer = 45673, + TrialAccessDoor = 45674, + TarAccessDoor = 45675, + AccessDoor = 45676, + BossAccessDoor = 45677, + SulphurAccessDoor = 45678, + }, + Orcs = { + Mission = 45679, + LookType = 45680, + BossTimer = 45681, + }, + Life = { + Mission = 45682, + BossTimer = 45683, + AccessDoor = 45684, + }, + Humans = { + Mission = 45685, + Vaporized = 45686, + Decaying = 45687, + BossTimer = 45688, + WallDecaying = 45689, + }, + Misguided = { + Mission = 45690, + Monsters = 45691, + Exorcisms = 45692, + Time = 45693, + BossTimer = 45694, + AccessDoor = 45695, + }, + FinalBoss = { + Mission = 45696, + BossTimer = 45697, + AccessDoor = 45698, + }, + }, ThreatenedDreams = { -- 45751 - 45850 QuestLine = 45751, Mission01 = { @@ -2589,7 +2462,110 @@ Storage = { }, }, U11_50 = { -- update 11.50 - Reserved Storages 45851 - 46000 - DangerousDepths = {}, + DangerousDepths = { + Questline = 45851, + Dwarves = { + Points = 45852, + Home = 45853, + Subterranean = 45854, + LostExiles = 45855, + Prisoners = 45856, + Organisms = 45857, + TimeTaskHome = 45858, + TimeTaskSubterranean = 45859, + }, + Scouts = { + Points = 45860, + Diremaw = 45861, + Growth = 45862, + DiremawsCount = 45863, + GnomishChest = 45864, + BarrelCount = 45865, + FirstBarrel = 45866, + SecondBarrel = 45867, + ThirdBarrel = 45868, + FourthBarrel = 45869, + FifthBarrel = 45870, + TimeTaskDiremaws = 45871, + TimeTaskGrowth = 45872, + Barrel = 45873, + BarrelTimer = 45874, + }, + Gnomes = { + Points = 45875, + Ordnance = 45876, + Measurements = 45877, + Charting = 45878, + GnomeChartChest = 45879, + GnomeChartPaper = 45880, + GnomesCount = 45881, + CrawlersCount = 45882, + LocationA = 45883, + LocationB = 45884, + LocationC = 45885, + LocationD = 45886, + LocationE = 45887, + LocationCount = 45888, + OldGate = 45889, + TheGaze = 45890, + LostRuin = 45891, + Outpost = 45892, + Bastion = 45893, + BrokenTower = 45894, + ChartingCount = 45895, + TimeTaskOrdnance = 45896, + TimeTaskMeasurements = 45897, + TimeTaskCharting = 45898, + }, + Access = { + LavaPumpWarzoneVI = 45899, + TimerWarzoneVI = 45900, + LavaPumpWarzoneV = 45901, + TimerWarzoneV = 45902, + LavaPumpWarzoneIV = 45903, + TimerWarzoneIV = 45904, + }, + Crystals = { + WarzoneVI = { + BigCrystal1 = 45905, + BigCrystal2 = 45906, + MediumCrystal1 = 45907, + MediumCrystal2 = 45908, + SmallCrystal1 = 45909, + SmallCrystal2 = 45910, + }, + WarzoneV = { + BigCrystal1 = 45911, + BigCrystal2 = 45912, + MediumCrystal1 = 45913, + MediumCrystal2 = 45914, + SmallCrystal1 = 45915, + SmallCrystal2 = 45916, + }, + WarzoneIV = { + BigCrystal1 = 45917, + BigCrystal2 = 45918, + MediumCrystal1 = 45919, + MediumCrystal2 = 45920, + SmallCrystal1 = 45921, + SmallCrystal2 = 45922, + }, + }, + Bosses = { + TheCountOfTheCore = 45923, + TheDukeOfTheDepths = 45924, + TheBaronFromBelow = 45925, + TheCountOfTheCoreAchiev = 45926, + TheDukeOfTheDepthsAchiev = 45927, + TheBaronFromBelowAchiev = 45928, + LastAchievement = 45929, + }, + Geodes = { + WarzoneVI = 45930, + WarzoneV = 45931, + WarzoneIV = 45932, + }, + }, HiddenThreats = { QuestLine = 45971, RatterDoor = 45972, @@ -2612,33 +2588,128 @@ Storage = { CorymRescued08 = 45987, CorymRescueMission = 45988, }, - MakeshiftWarriorOutfits = {}, }, U11_80 = { -- update 11.80 - Reserved Storages 46001 - 46300 - BattleMageOutfits = {}, - DiscovererOutfits = {}, - MeasuringTibia = {}, TheSecretLibrary = { - FalconBastionChestsTimer = { - Coast = 46281, - Island = 46282, - ThroneHall = 46283, - Shortcut = 46284, - LowerBastion = 46285, - UndergroundBastion = 46286, - }, - GhuloshTimer = 46015, - GhuloshKilled = 46016, - GorzindelTimer = 46017, - GorzindelKilled = 46018, - LokathmorTimer = 46019, - LokathmorKilled = 46020, - MazzinorTimer = 46021, - MazzinorKilled = 46022, - ScourgeOfOblivionDoor = 46023, - ScourgeOfOblivionTimer = 46024, - ScourgeOfOblivionKilled = 46025, + Questlog = 46001, + Asuras = { + Questline = 46002, + FlammingOrchid = 46003, + SkeletonNotes = 46004, + StrandHair = 46005, + LotusKey = 46006, + EyeKey = 46007, + ScribbledNotes = 46008, + EbonyPiece = 46009, + PeacockBallad = 46010, + BlackSkull = 46011, + SilverChimes = 46012, + DiamondTimer = 46013, + BlazingTimer = 46014, + DarkTimer = 46015, + Fragrance = 46016, + }, + FalconBastion = { + Questline = 46017, + KillingBosses = 46018, + OberonTimer = 46019, + OberonHeal = 46020, + LastBossMsgInterval = 46021, + OberonSay = 46022, + ChestsTimer = { + Coast = 46023, + Island = 46024, + ThroneHall = 46025, + Shortcut = 46026, + LowerBastion = 46027, + UndergroundBastion = 46028, + Key0909 = 46029, + }, + }, + Darashia = { + Questline = 46030, + PuzzleSqm = 46031, + FirstChest = 46032, + SecondChest = 46033, + ThirdChest = 46034, + FourthChest = 46035, + RedColor = 46036, + GreenColor = 46037, + BlueColor = 46038, + ColorPuzzle = 46039, + EatenFood = 46040, + FirstTotem = 46041, + SecondTotem = 46042, + ThirdTotem = 46043, + FourthTotem = 46044, + FifthChest = 46045, + ScorpionTimer = 46046, + }, + LiquidDeath = { + Questline = 46047, + Statue1 = 46048, + Statue2 = 46049, + Statue3 = 46050, + Statue4 = 46051, + Statue5 = 46052, + Statue6 = 46053, + Statue7 = 46054, + Statue8 = 46055, + Statue9 = 46056, + StatueCount = 46057, + BrokulTimer = 46058, + BrokulTimerGlobal = 46059, + }, + MoTA = { + Questline = 46060, + LeverPermission = 46061, + SampleBlood = 46062, + BonyRod = 46063, + BrokenCompass = 46064, + Crystal1 = 46065, + Crystal2 = 46066, + Crystal3 = 46067, + Crystal4 = 46068, + Crystal5 = 46069, + Crystal6 = 46070, + Crystal7 = 46071, + Crystal8 = 46072, + YellowGem = 46073, + GreenGem = 46074, + RedGem = 46075, + FinalBasin = 46076, + SkullSample = 46077, + TakenRod = 46078, + TrialTimer = 46079, + MuseumTimer = 46080, + }, + SmallIslands = { + Questline = 46081, + Parchment = 46082, + Sapphire = 46083, + Shovel = 46084, + Fishing = 46085, + RaxiasTimer = 46086, + BoatStages = 46087, + Hawser = 46088, + Turtle = 46089, + }, + LibraryPermission = 46090, + Library = { + Questline = 46091, + MazzinorTimer = 46092, + LokathmorTimer = 46093, + GhuloshTimer = 46094, + GorzindelTimer = 46095, + Ghulosh = 46096, + }, + }, + BattleMageOutfits = { + Addon1 = 46097, + Addon2 = 46098, }, + DiscovererOutfits = {}, + MeasuringTibia = {}, }, U12_00 = { -- update 12.00 - Reserved Storages 46301 - 46600 DreamWarriorOutfits = {}, @@ -2811,20 +2882,11 @@ Storage = { } GlobalStorage = { - DangerousDepths = { - -- Reserved storage from 60001 - 60009 - Geodes = { - WarzoneVI = 60001, - WarzoneV = 60002, - WarzoneIV = 60003, - }, - }, Feroxa = { -- Reserved storage from 60020 - 60029 Chance = 60020, Active = 60021, }, - HeroRathleton = { -- Reserved storage from 60070 - 60089 FirstMachines = 60070, @@ -2842,16 +2904,6 @@ GlobalStorage = { LavaChange = 60082, FastWay = 24867, }, - ForgottenKnowledge = { - -- Reserved storage from 60090 - 60099 - ActiveTree = 60090, - MechanismGolden = 60091, - MechanismDiamond = 60092, - GoldenServant = 60093, - DiamondServant = 60094, - AstralPowerCounter = 60095, - AstralGlyph = 60096, - }, TheOrderOfTheLion = { -- Reserved storage from 60170 - 60171 Drume = { diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua index f5b2d75f5ba..a6058bc4715 100644 --- a/data-otservbr-global/lib/quests/soul_war.lua +++ b/data-otservbr-global/lib/quests/soul_war.lua @@ -1455,7 +1455,7 @@ function Player:getSoulWarZoneMonster() return zoneMonsterName end -function Player:isInBoatSpot() +function Creature:isInBoatSpot() -- Get ebb and flow zone and check if player is in zone local zone = SoulWarQuest.ebbAndFlow.getZone() local tile = Tile(self:getPosition()) @@ -1464,11 +1464,11 @@ function Player:isInBoatSpot() groundId = tile:getGround():getId() end if zone and zone:isInZone(self:getPosition()) and tile and groundId == SoulWarQuest.ebbAndFlow.boatId then - logger.trace("Player {} is in boat spot", self:getName()) + logger.trace("Creature {} is in boat spot", self:getName()) return true end - logger.trace("Player {} is not in boat spot", self:getName()) + logger.trace("Creature {} is not in boat spot", self:getName()) return false end diff --git a/data-otservbr-global/migrations/46.lua b/data-otservbr-global/migrations/46.lua index 86a6d8ffec1..506da3a132b 100644 --- a/data-otservbr-global/migrations/46.lua +++ b/data-otservbr-global/migrations/46.lua @@ -1,3 +1,7 @@ function onUpdateDatabase() - return false -- true = There are others migrations file | false = this is the last migration file + logger.info("Updating database to version 47 (fix: creature speed and conditions)") + + db.query("ALTER TABLE `players` MODIFY `conditions` mediumblob NOT NULL;") + + return true end diff --git a/data-otservbr-global/migrations/47.lua b/data-otservbr-global/migrations/47.lua new file mode 100644 index 00000000000..86a6d8ffec1 --- /dev/null +++ b/data-otservbr-global/migrations/47.lua @@ -0,0 +1,3 @@ +function onUpdateDatabase() + return false -- true = There are others migrations file | false = this is the last migration file +end diff --git a/data-otservbr-global/monster/bosses/alchemist_container.lua b/data-otservbr-global/monster/bosses/alchemist_container.lua index 62905d5975e..5a15740a4f3 100644 --- a/data-otservbr-global/monster/bosses/alchemist_container.lua +++ b/data-otservbr-global/monster/bosses/alchemist_container.lua @@ -79,18 +79,4 @@ monster.immunities = { { 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/monster/bosses/antenna.lua b/data-otservbr-global/monster/bosses/antenna.lua index f1a165177cc..127d9fe77bf 100644 --- a/data-otservbr-global/monster/bosses/antenna.lua +++ b/data-otservbr-global/monster/bosses/antenna.lua @@ -79,18 +79,4 @@ monster.immunities = { { 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/monster/bosses/apocalypse.lua b/data-otservbr-global/monster/bosses/apocalypse.lua index 3e60fe75e34..422ebf84059 100644 --- a/data-otservbr-global/monster/bosses/apocalypse.lua +++ b/data-otservbr-global/monster/bosses/apocalypse.lua @@ -144,18 +144,4 @@ monster.immunities = { { 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/monster/bosses/apprentice_sheng.lua b/data-otservbr-global/monster/bosses/apprentice_sheng.lua index f0c6feacd95..b5d326f94a2 100644 --- a/data-otservbr-global/monster/bosses/apprentice_sheng.lua +++ b/data-otservbr-global/monster/bosses/apprentice_sheng.lua @@ -118,18 +118,4 @@ monster.immunities = { { 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/monster/bosses/armenius.lua b/data-otservbr-global/monster/bosses/armenius.lua index ffe6c7b412e..b80f2ff3b06 100644 --- a/data-otservbr-global/monster/bosses/armenius.lua +++ b/data-otservbr-global/monster/bosses/armenius.lua @@ -102,18 +102,4 @@ monster.immunities = { { 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/monster/bosses/bazir.lua b/data-otservbr-global/monster/bosses/bazir.lua index e9abbed723c..f9aa138933b 100644 --- a/data-otservbr-global/monster/bosses/bazir.lua +++ b/data-otservbr-global/monster/bosses/bazir.lua @@ -180,18 +180,4 @@ monster.immunities = { { 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/monster/bosses/bibby_bloodbath.lua b/data-otservbr-global/monster/bosses/bibby_bloodbath.lua index 8c1b09af2b5..d16b2f287d9 100644 --- a/data-otservbr-global/monster/bosses/bibby_bloodbath.lua +++ b/data-otservbr-global/monster/bosses/bibby_bloodbath.lua @@ -122,18 +122,4 @@ monster.immunities = { { 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/monster/bosses/big_boss_trolliver.lua b/data-otservbr-global/monster/bosses/big_boss_trolliver.lua index 24bc4ef5250..187b8e05d92 100644 --- a/data-otservbr-global/monster/bosses/big_boss_trolliver.lua +++ b/data-otservbr-global/monster/bosses/big_boss_trolliver.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/black_knight.lua b/data-otservbr-global/monster/bosses/black_knight.lua index 2905e1a7814..359ef3e2d5b 100644 --- a/data-otservbr-global/monster/bosses/black_knight.lua +++ b/data-otservbr-global/monster/bosses/black_knight.lua @@ -131,18 +131,4 @@ monster.immunities = { { 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/monster/bosses/brain_head.lua b/data-otservbr-global/monster/bosses/brain_head.lua index c67524c5411..0c8b59b4a4a 100644 --- a/data-otservbr-global/monster/bosses/brain_head.lua +++ b/data-otservbr-global/monster/bosses/brain_head.lua @@ -102,18 +102,4 @@ monster.voices = { { text = "My lich-knights will conquer this world for me!", yell = 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/monster/bosses/bullwark.lua b/data-otservbr-global/monster/bosses/bullwark.lua index 2bc9ff91f02..2ae627598c9 100644 --- a/data-otservbr-global/monster/bosses/bullwark.lua +++ b/data-otservbr-global/monster/bosses/bullwark.lua @@ -127,18 +127,4 @@ monster.immunities = { { 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/monster/bosses/cerebellum.lua b/data-otservbr-global/monster/bosses/cerebellum.lua index b83fcec8615..5ca05351efb 100644 --- a/data-otservbr-global/monster/bosses/cerebellum.lua +++ b/data-otservbr-global/monster/bosses/cerebellum.lua @@ -77,18 +77,4 @@ monster.voices = { { text = "My lich-knights will conquer this world for me!", yell = 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/monster/bosses/chikhaton.lua b/data-otservbr-global/monster/bosses/chikhaton.lua index 53a430621ca..63b5629431c 100644 --- a/data-otservbr-global/monster/bosses/chikhaton.lua +++ b/data-otservbr-global/monster/bosses/chikhaton.lua @@ -102,18 +102,4 @@ monster.immunities = { { 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/monster/bosses/clubarc_the_plunderer.lua b/data-otservbr-global/monster/bosses/clubarc_the_plunderer.lua index aa10611af90..d2e7ca6c29f 100644 --- a/data-otservbr-global/monster/bosses/clubarc_the_plunderer.lua +++ b/data-otservbr-global/monster/bosses/clubarc_the_plunderer.lua @@ -108,18 +108,4 @@ monster.immunities = { { 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/monster/bosses/custodian.lua b/data-otservbr-global/monster/bosses/custodian.lua index d004ab5c3df..2a2e414d3d9 100644 --- a/data-otservbr-global/monster/bosses/custodian.lua +++ b/data-otservbr-global/monster/bosses/custodian.lua @@ -113,18 +113,4 @@ monster.immunities = { { 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/monster/bosses/dharalion.lua b/data-otservbr-global/monster/bosses/dharalion.lua index 3233e57448b..9268919df94 100644 --- a/data-otservbr-global/monster/bosses/dharalion.lua +++ b/data-otservbr-global/monster/bosses/dharalion.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/bosses/diblis_the_fair.lua b/data-otservbr-global/monster/bosses/diblis_the_fair.lua index 531dc6c2818..585fb0eff0a 100644 --- a/data-otservbr-global/monster/bosses/diblis_the_fair.lua +++ b/data-otservbr-global/monster/bosses/diblis_the_fair.lua @@ -123,18 +123,4 @@ monster.immunities = { { 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/monster/bosses/diseased_bill.lua b/data-otservbr-global/monster/bosses/diseased_bill.lua index 42df3b5c771..bc6babe9171 100644 --- a/data-otservbr-global/monster/bosses/diseased_bill.lua +++ b/data-otservbr-global/monster/bosses/diseased_bill.lua @@ -114,18 +114,4 @@ monster.immunities = { { 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/monster/bosses/diseased_dan.lua b/data-otservbr-global/monster/bosses/diseased_dan.lua index c44f9bc9702..f3b0de85388 100644 --- a/data-otservbr-global/monster/bosses/diseased_dan.lua +++ b/data-otservbr-global/monster/bosses/diseased_dan.lua @@ -114,18 +114,4 @@ monster.immunities = { { 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/monster/bosses/diseased_fred.lua b/data-otservbr-global/monster/bosses/diseased_fred.lua index 59304042e5c..41994a777ea 100644 --- a/data-otservbr-global/monster/bosses/diseased_fred.lua +++ b/data-otservbr-global/monster/bosses/diseased_fred.lua @@ -114,18 +114,4 @@ monster.immunities = { { 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/monster/bosses/doctor_marrow.lua b/data-otservbr-global/monster/bosses/doctor_marrow.lua index cccdd2e4d57..cd694d83b62 100644 --- a/data-otservbr-global/monster/bosses/doctor_marrow.lua +++ b/data-otservbr-global/monster/bosses/doctor_marrow.lua @@ -98,18 +98,4 @@ monster.immunities = { { 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/monster/bosses/ekatrix.lua b/data-otservbr-global/monster/bosses/ekatrix.lua index 99c7fc0f603..42500ee134f 100644 --- a/data-otservbr-global/monster/bosses/ekatrix.lua +++ b/data-otservbr-global/monster/bosses/ekatrix.lua @@ -111,18 +111,4 @@ monster.immunities = { { 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/monster/bosses/energized_raging_mage.lua b/data-otservbr-global/monster/bosses/energized_raging_mage.lua index 0d3aea8aaf0..643ea7428a3 100644 --- a/data-otservbr-global/monster/bosses/energized_raging_mage.lua +++ b/data-otservbr-global/monster/bosses/energized_raging_mage.lua @@ -115,18 +115,4 @@ monster.immunities = { { 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/monster/bosses/fleshslicer.lua b/data-otservbr-global/monster/bosses/fleshslicer.lua index 53aafc0fd31..7308101c0d4 100644 --- a/data-otservbr-global/monster/bosses/fleshslicer.lua +++ b/data-otservbr-global/monster/bosses/fleshslicer.lua @@ -99,18 +99,4 @@ monster.immunities = { { 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/monster/bosses/freegoiz.lua b/data-otservbr-global/monster/bosses/freegoiz.lua index eee6234add3..8f2ad6839b3 100644 --- a/data-otservbr-global/monster/bosses/freegoiz.lua +++ b/data-otservbr-global/monster/bosses/freegoiz.lua @@ -167,18 +167,4 @@ monster.immunities = { { 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/monster/bosses/gaffir.lua b/data-otservbr-global/monster/bosses/gaffir.lua index a3e2feb16a6..a51115cb094 100644 --- a/data-otservbr-global/monster/bosses/gaffir.lua +++ b/data-otservbr-global/monster/bosses/gaffir.lua @@ -141,18 +141,4 @@ monster.immunities = { { 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/monster/bosses/general_murius.lua b/data-otservbr-global/monster/bosses/general_murius.lua index 4c761e0b89f..f3cf1837f0f 100644 --- a/data-otservbr-global/monster/bosses/general_murius.lua +++ b/data-otservbr-global/monster/bosses/general_murius.lua @@ -129,18 +129,4 @@ monster.immunities = { { 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/monster/bosses/glitterscale.lua b/data-otservbr-global/monster/bosses/glitterscale.lua index 0705a895176..c14fae7f785 100644 --- a/data-otservbr-global/monster/bosses/glitterscale.lua +++ b/data-otservbr-global/monster/bosses/glitterscale.lua @@ -101,18 +101,4 @@ monster.immunities = { { 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/monster/bosses/grandfather_tridian.lua b/data-otservbr-global/monster/bosses/grandfather_tridian.lua index 6c2f0e9f188..3d58c8d768d 100644 --- a/data-otservbr-global/monster/bosses/grandfather_tridian.lua +++ b/data-otservbr-global/monster/bosses/grandfather_tridian.lua @@ -124,18 +124,4 @@ monster.immunities = { { 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/monster/bosses/gravelord_oshuran.lua b/data-otservbr-global/monster/bosses/gravelord_oshuran.lua index 442c014dcbb..53ed2381c4f 100644 --- a/data-otservbr-global/monster/bosses/gravelord_oshuran.lua +++ b/data-otservbr-global/monster/bosses/gravelord_oshuran.lua @@ -121,18 +121,4 @@ monster.immunities = { { 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/monster/bosses/groam.lua b/data-otservbr-global/monster/bosses/groam.lua index e010d50e708..8e9e56a2c5f 100644 --- a/data-otservbr-global/monster/bosses/groam.lua +++ b/data-otservbr-global/monster/bosses/groam.lua @@ -109,18 +109,4 @@ monster.immunities = { { 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/monster/bosses/guard_captain_quaid.lua b/data-otservbr-global/monster/bosses/guard_captain_quaid.lua index 479757ca620..85507170974 100644 --- a/data-otservbr-global/monster/bosses/guard_captain_quaid.lua +++ b/data-otservbr-global/monster/bosses/guard_captain_quaid.lua @@ -126,18 +126,4 @@ monster.immunities = { { 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/monster/bosses/hairman_the_huge.lua b/data-otservbr-global/monster/bosses/hairman_the_huge.lua index 735c1b3b263..5b0aa24de1d 100644 --- a/data-otservbr-global/monster/bosses/hairman_the_huge.lua +++ b/data-otservbr-global/monster/bosses/hairman_the_huge.lua @@ -107,18 +107,4 @@ monster.immunities = { { 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/monster/bosses/heoni.lua b/data-otservbr-global/monster/bosses/heoni.lua index b5e9cfdcfd3..9f099de756d 100644 --- a/data-otservbr-global/monster/bosses/heoni.lua +++ b/data-otservbr-global/monster/bosses/heoni.lua @@ -105,18 +105,4 @@ monster.immunities = { { 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/monster/bosses/incredibly_old_witch.lua b/data-otservbr-global/monster/bosses/incredibly_old_witch.lua index 8680042f7ca..4cd69a5fef2 100644 --- a/data-otservbr-global/monster/bosses/incredibly_old_witch.lua +++ b/data-otservbr-global/monster/bosses/incredibly_old_witch.lua @@ -104,18 +104,4 @@ monster.immunities = { { 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/monster/bosses/infernatil.lua b/data-otservbr-global/monster/bosses/infernatil.lua index c7ca8c53050..0a493c91177 100644 --- a/data-otservbr-global/monster/bosses/infernatil.lua +++ b/data-otservbr-global/monster/bosses/infernatil.lua @@ -176,18 +176,4 @@ monster.immunities = { { 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/monster/bosses/koshei_the_deathless.lua b/data-otservbr-global/monster/bosses/koshei_the_deathless.lua index e0b1c5e1ecc..ff6cc6e8654 100644 --- a/data-otservbr-global/monster/bosses/koshei_the_deathless.lua +++ b/data-otservbr-global/monster/bosses/koshei_the_deathless.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/kraknaknork's_demon.lua b/data-otservbr-global/monster/bosses/kraknaknork's_demon.lua index 8902bd9e527..a1579035a6f 100644 --- a/data-otservbr-global/monster/bosses/kraknaknork's_demon.lua +++ b/data-otservbr-global/monster/bosses/kraknaknork's_demon.lua @@ -97,18 +97,4 @@ monster.immunities = { { 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/monster/bosses/kraknaknork.lua b/data-otservbr-global/monster/bosses/kraknaknork.lua index 2bb4eb32b4a..c639a0c8bfd 100644 --- a/data-otservbr-global/monster/bosses/kraknaknork.lua +++ b/data-otservbr-global/monster/bosses/kraknaknork.lua @@ -112,14 +112,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onThink = function(monster, interval) end - -mType.onAppear = function(monster, creature) 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/monster/bosses/kroazur.lua b/data-otservbr-global/monster/bosses/kroazur.lua index 1664c14347a..ea38b19db8f 100644 --- a/data-otservbr-global/monster/bosses/kroazur.lua +++ b/data-otservbr-global/monster/bosses/kroazur.lua @@ -127,18 +127,4 @@ monster.immunities = { { 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/monster/bosses/lisa.lua b/data-otservbr-global/monster/bosses/lisa.lua index 7cbff8d7d49..2890e8d692a 100644 --- a/data-otservbr-global/monster/bosses/lisa.lua +++ b/data-otservbr-global/monster/bosses/lisa.lua @@ -130,18 +130,4 @@ monster.immunities = { { 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/monster/bosses/mad_mage.lua b/data-otservbr-global/monster/bosses/mad_mage.lua index 2ff8144d310..307f26a9aa0 100644 --- a/data-otservbr-global/monster/bosses/mad_mage.lua +++ b/data-otservbr-global/monster/bosses/mad_mage.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/bosses/mad_technomancer.lua b/data-otservbr-global/monster/bosses/mad_technomancer.lua index 7d72216b88a..0a329a858a6 100644 --- a/data-otservbr-global/monster/bosses/mad_technomancer.lua +++ b/data-otservbr-global/monster/bosses/mad_technomancer.lua @@ -104,18 +104,4 @@ monster.immunities = { { 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/monster/bosses/morik_the_gladiator.lua b/data-otservbr-global/monster/bosses/morik_the_gladiator.lua index 5a8a012ca84..670294b12e8 100644 --- a/data-otservbr-global/monster/bosses/morik_the_gladiator.lua +++ b/data-otservbr-global/monster/bosses/morik_the_gladiator.lua @@ -109,18 +109,4 @@ monster.immunities = { { 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/monster/bosses/morshabaal.lua b/data-otservbr-global/monster/bosses/morshabaal.lua index 4273977e2eb..363c103cad2 100644 --- a/data-otservbr-global/monster/bosses/morshabaal.lua +++ b/data-otservbr-global/monster/bosses/morshabaal.lua @@ -145,10 +145,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/bosses/munster.lua b/data-otservbr-global/monster/bosses/munster.lua index daeeac7655e..21c2761d0f8 100644 --- a/data-otservbr-global/monster/bosses/munster.lua +++ b/data-otservbr-global/monster/bosses/munster.lua @@ -109,18 +109,4 @@ monster.immunities = { { 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/monster/bosses/pythius_the_rotten.lua b/data-otservbr-global/monster/bosses/pythius_the_rotten.lua index 80f694af6bc..742285c193f 100644 --- a/data-otservbr-global/monster/bosses/pythius_the_rotten.lua +++ b/data-otservbr-global/monster/bosses/pythius_the_rotten.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/raging_mage.lua b/data-otservbr-global/monster/bosses/raging_mage.lua index 5fd30131b8a..84e0232f37f 100644 --- a/data-otservbr-global/monster/bosses/raging_mage.lua +++ b/data-otservbr-global/monster/bosses/raging_mage.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/bosses/raxias.lua b/data-otservbr-global/monster/bosses/raxias.lua index ea62576f52d..3f0f7cf1ce6 100644 --- a/data-otservbr-global/monster/bosses/raxias.lua +++ b/data-otservbr-global/monster/bosses/raxias.lua @@ -103,18 +103,4 @@ monster.immunities = { { 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/monster/bosses/renegade_orc.lua b/data-otservbr-global/monster/bosses/renegade_orc.lua index 53f075751ae..157b75d352a 100644 --- a/data-otservbr-global/monster/bosses/renegade_orc.lua +++ b/data-otservbr-global/monster/bosses/renegade_orc.lua @@ -115,18 +115,4 @@ monster.immunities = { { 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/monster/bosses/rukor_zad.lua b/data-otservbr-global/monster/bosses/rukor_zad.lua index 361365745b5..bbcf1706943 100644 --- a/data-otservbr-global/monster/bosses/rukor_zad.lua +++ b/data-otservbr-global/monster/bosses/rukor_zad.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/smuggler_baron_silvertoe.lua b/data-otservbr-global/monster/bosses/smuggler_baron_silvertoe.lua index b59d09d2387..c35cc2dcf40 100644 --- a/data-otservbr-global/monster/bosses/smuggler_baron_silvertoe.lua +++ b/data-otservbr-global/monster/bosses/smuggler_baron_silvertoe.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/spider_queen.lua b/data-otservbr-global/monster/bosses/spider_queen.lua index 1f2b018f26c..88a0aa939c1 100644 --- a/data-otservbr-global/monster/bosses/spider_queen.lua +++ b/data-otservbr-global/monster/bosses/spider_queen.lua @@ -94,18 +94,4 @@ monster.immunities = { { 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/monster/bosses/splasher.lua b/data-otservbr-global/monster/bosses/splasher.lua index 426d3be3c26..825f56607db 100644 --- a/data-otservbr-global/monster/bosses/splasher.lua +++ b/data-otservbr-global/monster/bosses/splasher.lua @@ -110,18 +110,4 @@ monster.immunities = { { 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/monster/bosses/teleskor.lua b/data-otservbr-global/monster/bosses/teleskor.lua index 0c27b032658..e5941477479 100644 --- a/data-otservbr-global/monster/bosses/teleskor.lua +++ b/data-otservbr-global/monster/bosses/teleskor.lua @@ -104,18 +104,4 @@ monster.immunities = { { 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/monster/bosses/the_abomination.lua b/data-otservbr-global/monster/bosses/the_abomination.lua index e6ba0b1ae06..0249b2453ae 100644 --- a/data-otservbr-global/monster/bosses/the_abomination.lua +++ b/data-otservbr-global/monster/bosses/the_abomination.lua @@ -125,18 +125,4 @@ monster.immunities = { { 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/monster/bosses/the_astral_source.lua b/data-otservbr-global/monster/bosses/the_astral_source.lua index abc46bfc1d4..008da5078b5 100644 --- a/data-otservbr-global/monster/bosses/the_astral_source.lua +++ b/data-otservbr-global/monster/bosses/the_astral_source.lua @@ -96,18 +96,4 @@ monster.immunities = { { 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/monster/bosses/the_blightfather.lua b/data-otservbr-global/monster/bosses/the_blightfather.lua index 1cb8c870901..7e1c0515e87 100644 --- a/data-otservbr-global/monster/bosses/the_blightfather.lua +++ b/data-otservbr-global/monster/bosses/the_blightfather.lua @@ -108,18 +108,4 @@ monster.immunities = { { 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/monster/bosses/the_book_of_death.lua b/data-otservbr-global/monster/bosses/the_book_of_death.lua index 6cea3d844aa..53d37c08795 100644 --- a/data-otservbr-global/monster/bosses/the_book_of_death.lua +++ b/data-otservbr-global/monster/bosses/the_book_of_death.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 39 monster.manaCost = 0 +monster.events = { + "ghuloshDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, @@ -96,18 +100,4 @@ monster.immunities = { { 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/monster/bosses/the_brainstealer.lua b/data-otservbr-global/monster/bosses/the_brainstealer.lua index 57a4beba537..78d783d4618 100644 --- a/data-otservbr-global/monster/bosses/the_brainstealer.lua +++ b/data-otservbr-global/monster/bosses/the_brainstealer.lua @@ -129,18 +129,4 @@ monster.voices = { { text = "My lich-knights will conquer this world for me!", yell = 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/monster/bosses/the_collector.lua b/data-otservbr-global/monster/bosses/the_collector.lua index b3fa70f85c6..5fd5a4a6336 100644 --- a/data-otservbr-global/monster/bosses/the_collector.lua +++ b/data-otservbr-global/monster/bosses/the_collector.lua @@ -98,18 +98,4 @@ monster.immunities = { { 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/monster/bosses/the_evil_eye.lua b/data-otservbr-global/monster/bosses/the_evil_eye.lua index f712959cdd7..b3be845c629 100644 --- a/data-otservbr-global/monster/bosses/the_evil_eye.lua +++ b/data-otservbr-global/monster/bosses/the_evil_eye.lua @@ -123,18 +123,4 @@ monster.immunities = { { 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/monster/bosses/the_first_dragon.lua b/data-otservbr-global/monster/bosses/the_first_dragon.lua index 34294280dd1..921f8394622 100644 --- a/data-otservbr-global/monster/bosses/the_first_dragon.lua +++ b/data-otservbr-global/monster/bosses/the_first_dragon.lua @@ -108,18 +108,4 @@ monster.immunities = { { 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/monster/bosses/the_flaming_orchid.lua b/data-otservbr-global/monster/bosses/the_flaming_orchid.lua new file mode 100644 index 00000000000..4ab6508475e --- /dev/null +++ b/data-otservbr-global/monster/bosses/the_flaming_orchid.lua @@ -0,0 +1,126 @@ +local mType = Game.createMonsterType("The Flaming Orchid") +local monster = {} + +monster.description = "a flaming orchid" +monster.experience = 8500 +monster.outfit = { + lookType = 150, + lookHead = 114, + lookBody = 94, + lookLegs = 78, + lookFeet = 79, + lookAddons = 1, + lookMount = 0, +} + +monster.health = 4000 +monster.maxHealth = 4000 +monster.race = "blood" +monster.corpse = 21987 -- review later +monster.speed = 210 +monster.manaCost = 0 + +monster.events = { + "killingLibrary", +} + +monster.changeTarget = { + interval = 4000, + chance = 10, +} + +monster.strategiesTarget = { + nearest = 100, +} + +monster.flags = { + summonable = false, + attackable = true, + hostile = true, + convinceable = false, + pushable = false, + rewardBoss = false, + illusionable = true, + canPushItems = true, + canPushCreatures = true, + staticAttackChance = 80, + targetDistance = 1, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = true, + canWalkOnFire = true, + canWalkOnPoison = true, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.voices = { + interval = 2000, + chance = 7, + { text = "I will end your torment. Do not run, little mortal.", yell = true }, + { text = "*SNIFF* *SNIFF* BLOOD! I CAN SMELL YOU, MORTAL!!", yell = true }, +} + +monster.loot = { + { name = "gold coin", chance = 100000, maxCount = 250 }, + { name = "platinum coin", chance = 9240, maxCount = 10 }, + { id = 3039, chance = 18200 }, -- red gem + { name = "gold ingot", chance = 29700, maxCount = 5 }, + { name = "assassin star", chance = 29700, maxCount = 13 }, + { name = "demonic essence", chance = 330 }, + { name = "great spirit potion", chance = 330 }, + { name = "soul orb", chance = 19530 }, + { name = "small amethyst", chance = 8310, maxCount = 2 }, + { name = "small amethyst", chance = 8310, maxCount = 2 }, + { name = "ultimate health potion", chance = 700, maxCount = 4 }, + { name = "golden lotus brooch", chance = 19740 }, + { name = "green gem", chance = 15780 }, + { name = "magma coat", chance = 1050 }, + { name = "moonlight rod", chance = 1050 }, + { name = "necrotic rod", chance = 1050 }, + { name = "oriental shoes", chance = 490 }, + { name = "peacock feather fan", chance = 16870 }, +} + +monster.attacks = { + { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -25 }, + { name = "combat", interval = 1000, chance = 10, type = COMBAT_DEATHDAMAGE, minDamage = -400, maxDamage = -700, range = 7, effect = CONST_ANI_DEATH, target = true }, + { name = "Ignite", interval = 2000, chance = 20, range = 7, radius = 1, target = true, shootEffect = CONST_ANI_FIRE }, + { name = "big death wave", interval = 4000, chance = 18, minDamage = 0, maxDamage = -500 }, -- review later + { name = "aggressivelavawave", interval = 5000, chance = 19, minDamage = 0, maxDamage = -200 }, -- review later + { name = "combat", interval = 6000, chance = 20, type = COMBAT_FIREDAMAGE, range = 5, radius = 7, target = true, minDamage = -100, maxDamage = -250, shootEffect = CONST_ANI_FIRE, effect = CONST_ME_FIREAREA, target = false }, +} + +monster.defenses = { + defense = 55, + armor = 55, + { name = "combat", interval = 2000, chance = 15, type = COMBAT_HEALING, minDamage = 50, maxDamage = 280, effect = CONST_ME_MAGIC_BLUE, target = false }, + { name = "speed", interval = 2000, chance = 15, speedChange = 320, duration = 5000, areaEffect = CONST_ME_MAGIC_RED }, + { name = "invisible", interval = 1000, chance = 100, duration = 10000, areaEffect = CONST_ME_MAGIC_BLUE }, +} + +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:register(monster) diff --git a/data-otservbr-global/monster/bosses/the_frog_prince.lua b/data-otservbr-global/monster/bosses/the_frog_prince.lua index d90c6c78b2e..745757dc621 100644 --- a/data-otservbr-global/monster/bosses/the_frog_prince.lua +++ b/data-otservbr-global/monster/bosses/the_frog_prince.lua @@ -102,18 +102,4 @@ monster.immunities = { { 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/monster/bosses/the_monster.lua b/data-otservbr-global/monster/bosses/the_monster.lua index c7f84935b20..368bff98af0 100644 --- a/data-otservbr-global/monster/bosses/the_monster.lua +++ b/data-otservbr-global/monster/bosses/the_monster.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/bosses/verminor.lua b/data-otservbr-global/monster/bosses/verminor.lua index 1712cccab2e..43b4c194257 100644 --- a/data-otservbr-global/monster/bosses/verminor.lua +++ b/data-otservbr-global/monster/bosses/verminor.lua @@ -166,18 +166,4 @@ monster.immunities = { { 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/monster/bosses/visco.lua b/data-otservbr-global/monster/bosses/visco.lua index 96223ee28c0..d78729aeaf6 100644 --- a/data-otservbr-global/monster/bosses/visco.lua +++ b/data-otservbr-global/monster/bosses/visco.lua @@ -124,18 +124,4 @@ monster.immunities = { { 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/monster/bosses/warlord_ruzad.lua b/data-otservbr-global/monster/bosses/warlord_ruzad.lua index b66a9c3284b..1970e2d47f6 100644 --- a/data-otservbr-global/monster/bosses/warlord_ruzad.lua +++ b/data-otservbr-global/monster/bosses/warlord_ruzad.lua @@ -124,18 +124,4 @@ monster.immunities = { { 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/monster/bosses/weakened_demon.lua b/data-otservbr-global/monster/bosses/weakened_demon.lua index 7daf2f5dfb2..936849b379f 100644 --- a/data-otservbr-global/monster/bosses/weakened_demon.lua +++ b/data-otservbr-global/monster/bosses/weakened_demon.lua @@ -95,14 +95,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onThink = function(monster, interval) end - -mType.onAppear = function(monster, creature) 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/monster/bosses/weakened_shlorg.lua b/data-otservbr-global/monster/bosses/weakened_shlorg.lua index 615bd45f158..3734d602406 100644 --- a/data-otservbr-global/monster/bosses/weakened_shlorg.lua +++ b/data-otservbr-global/monster/bosses/weakened_shlorg.lua @@ -122,18 +122,4 @@ monster.immunities = { { 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/monster/bosses/williwasp.lua b/data-otservbr-global/monster/bosses/williwasp.lua index 64a90d09de1..93868eba760 100644 --- a/data-otservbr-global/monster/bosses/williwasp.lua +++ b/data-otservbr-global/monster/bosses/williwasp.lua @@ -104,18 +104,4 @@ monster.immunities = { { 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/monster/bosses/yaga_the_crone.lua b/data-otservbr-global/monster/bosses/yaga_the_crone.lua index 4987d01b4c2..5f47c5c907c 100644 --- a/data-otservbr-global/monster/bosses/yaga_the_crone.lua +++ b/data-otservbr-global/monster/bosses/yaga_the_crone.lua @@ -120,18 +120,4 @@ monster.immunities = { { 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/monster/bosses/zarabustor.lua b/data-otservbr-global/monster/bosses/zarabustor.lua index 8bb36a5e904..fbe771c51b9 100644 --- a/data-otservbr-global/monster/bosses/zarabustor.lua +++ b/data-otservbr-global/monster/bosses/zarabustor.lua @@ -128,18 +128,4 @@ monster.immunities = { { 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/monster/bosses/zavarash.lua b/data-otservbr-global/monster/bosses/zavarash.lua index a3f41dc6d04..3fd5b60c1e4 100644 --- a/data-otservbr-global/monster/bosses/zavarash.lua +++ b/data-otservbr-global/monster/bosses/zavarash.lua @@ -136,18 +136,4 @@ monster.immunities = { { 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/monster/bosses/zevelon_duskbringer.lua b/data-otservbr-global/monster/bosses/zevelon_duskbringer.lua index 7dd4739741e..836ecdf37c2 100644 --- a/data-otservbr-global/monster/bosses/zevelon_duskbringer.lua +++ b/data-otservbr-global/monster/bosses/zevelon_duskbringer.lua @@ -124,18 +124,4 @@ monster.immunities = { { 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/monster/bosses/zoralurk.lua b/data-otservbr-global/monster/bosses/zoralurk.lua index e8095a70f68..6afc231f0d9 100644 --- a/data-otservbr-global/monster/bosses/zoralurk.lua +++ b/data-otservbr-global/monster/bosses/zoralurk.lua @@ -125,18 +125,4 @@ monster.immunities = { { 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/monster/bosses/zushuka.lua b/data-otservbr-global/monster/bosses/zushuka.lua index 2491261be7b..6e5c027d4c4 100644 --- a/data-otservbr-global/monster/bosses/zushuka.lua +++ b/data-otservbr-global/monster/bosses/zushuka.lua @@ -145,18 +145,4 @@ monster.immunities = { { 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/monster/constructs/iron_servant_replica.lua b/data-otservbr-global/monster/constructs/iron_servant_replica.lua index 4ff09899972..a0fa2c74c74 100644 --- a/data-otservbr-global/monster/constructs/iron_servant_replica.lua +++ b/data-otservbr-global/monster/constructs/iron_servant_replica.lua @@ -113,4 +113,27 @@ monster.immunities = { { type = "bleed", condition = false }, } +mType.onSpawn = function(monster) + local chance = math.random(100) + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismDiamond) >= 1 and Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismGolden) >= 1 then + if chance > 30 then + local monsterType = math.random(2) == 1 and "diamond servant replica" or "golden servant replica" + Game.createMonster(monsterType, monster:getPosition(), false, true) + monster:remove() + end + return + end + + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismDiamond) >= 1 and chance > 30 then + Game.createMonster("diamond servant replica", monster:getPosition(), false, true) + monster:remove() + return + end + + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismGolden) >= 1 and chance > 30 then + Game.createMonster("golden servant replica", monster:getPosition(), false, true) + monster:remove() + end +end + mType:register(monster) diff --git a/data-otservbr-global/monster/event_creatures/the_mutated_pumpkin.lua b/data-otservbr-global/monster/event_creatures/the_mutated_pumpkin.lua index 5e219736804..4abdfe16340 100644 --- a/data-otservbr-global/monster/event_creatures/the_mutated_pumpkin.lua +++ b/data-otservbr-global/monster/event_creatures/the_mutated_pumpkin.lua @@ -130,18 +130,4 @@ monster.immunities = { { 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/monster/humans/cobra_assassin.lua b/data-otservbr-global/monster/humans/cobra_assassin.lua index a2206a77ad5..fa834503e56 100644 --- a/data-otservbr-global/monster/humans/cobra_assassin.lua +++ b/data-otservbr-global/monster/humans/cobra_assassin.lua @@ -121,4 +121,8 @@ monster.immunities = { { type = "bleed", condition = false }, } +mType.onSpawn = function(monster) + monster:handleCobraOnSpawn() +end + mType:register(monster) diff --git a/data-otservbr-global/monster/humans/cobra_scout.lua b/data-otservbr-global/monster/humans/cobra_scout.lua index 7aded2b24ec..6fc3e893497 100644 --- a/data-otservbr-global/monster/humans/cobra_scout.lua +++ b/data-otservbr-global/monster/humans/cobra_scout.lua @@ -126,4 +126,8 @@ monster.immunities = { { type = "bleed", condition = false }, } +mType.onSpawn = function(monster) + monster:handleCobraOnSpawn() +end + mType:register(monster) diff --git a/data-otservbr-global/monster/humans/cobra_vizier.lua b/data-otservbr-global/monster/humans/cobra_vizier.lua index c6052ab7829..934b015842a 100644 --- a/data-otservbr-global/monster/humans/cobra_vizier.lua +++ b/data-otservbr-global/monster/humans/cobra_vizier.lua @@ -129,4 +129,8 @@ monster.immunities = { { type = "bleed", condition = false }, } +mType.onSpawn = function(monster) + monster:handleCobraOnSpawn() +end + mType:register(monster) diff --git a/data-otservbr-global/monster/quests/a_pirates_tail_quest/ratmiral_blackwhiskers.lua b/data-otservbr-global/monster/quests/a_pirates_tail_quest/ratmiral_blackwhiskers.lua index d399413ed93..03a093b3afb 100644 --- a/data-otservbr-global/monster/quests/a_pirates_tail_quest/ratmiral_blackwhiskers.lua +++ b/data-otservbr-global/monster/quests/a_pirates_tail_quest/ratmiral_blackwhiskers.lua @@ -141,10 +141,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/a_pirates_tail_quest/tentuglys_head.lua b/data-otservbr-global/monster/quests/a_pirates_tail_quest/tentuglys_head.lua index 07fef10a1fd..2fe0c2d05ce 100644 --- a/data-otservbr-global/monster/quests/a_pirates_tail_quest/tentuglys_head.lua +++ b/data-otservbr-global/monster/quests/a_pirates_tail_quest/tentuglys_head.lua @@ -121,10 +121,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/adventures_of_galthen/megasylvan_yselda.lua b/data-otservbr-global/monster/quests/adventures_of_galthen/megasylvan_yselda.lua index 606427d8afe..d3343d38d23 100644 --- a/data-otservbr-global/monster/quests/adventures_of_galthen/megasylvan_yselda.lua +++ b/data-otservbr-global/monster/quests/adventures_of_galthen/megasylvan_yselda.lua @@ -128,10 +128,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/ancient_feud/katex_blood_tongue.lua b/data-otservbr-global/monster/quests/ancient_feud/katex_blood_tongue.lua index b6806adbed6..5c7ff8775e3 100644 --- a/data-otservbr-global/monster/quests/ancient_feud/katex_blood_tongue.lua +++ b/data-otservbr-global/monster/quests/ancient_feud/katex_blood_tongue.lua @@ -134,10 +134,4 @@ monster.immunities = { { type = "bleed", condition = true }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/ancient_feud/srezz_yellow_eyes.lua b/data-otservbr-global/monster/quests/ancient_feud/srezz_yellow_eyes.lua index 3c849c72aa3..5246bf87bc4 100644 --- a/data-otservbr-global/monster/quests/ancient_feud/srezz_yellow_eyes.lua +++ b/data-otservbr-global/monster/quests/ancient_feud/srezz_yellow_eyes.lua @@ -128,10 +128,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/ancient_feud/utua_stone_sting.lua b/data-otservbr-global/monster/quests/ancient_feud/utua_stone_sting.lua index 511c78787aa..06562f10883 100644 --- a/data-otservbr-global/monster/quests/ancient_feud/utua_stone_sting.lua +++ b/data-otservbr-global/monster/quests/ancient_feud/utua_stone_sting.lua @@ -131,10 +131,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/ancient_feud/yirkas_blue_scales.lua b/data-otservbr-global/monster/quests/ancient_feud/yirkas_blue_scales.lua index e469fa36986..1b170cb7447 100644 --- a/data-otservbr-global/monster/quests/ancient_feud/yirkas_blue_scales.lua +++ b/data-otservbr-global/monster/quests/ancient_feud/yirkas_blue_scales.lua @@ -129,10 +129,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua index 26aceb32010..c1cd61949aa 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/essence_of_malice.lua @@ -130,18 +130,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua index e3eef7671c6..cf456f603fb 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/ravenous_hunger.lua @@ -145,18 +145,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/the_false_god.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua index a1ec678bdf0..fc7fc63b2ad 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_false_god.lua @@ -139,18 +139,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/the_sandking.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua index 3e0914007db..ecddb810da0 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_sandking.lua @@ -144,18 +144,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua index 976fe5fe317..b6d08409ec8 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_souldespoiler.lua @@ -155,18 +155,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua index 83f14ead593..3361299d9a9 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_source_of_corruption.lua @@ -117,18 +117,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua index 04df78685ac..42fc6498721 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/bosses/the_unarmored_voidborn.lua @@ -136,18 +136,4 @@ monster.immunities = { { 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/monster/quests/cults_of_tibia/misguided_bully.lua b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua index 5cf1c3b8582..0798c14fe70 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_bully.lua @@ -13,10 +13,6 @@ monster.outfit = { lookMount = 0, } -monster.events = { - "GlowingRubbishAmuletDeath", -} - monster.raceId = 1412 monster.Bestiary = { class = "Humanoid", @@ -49,6 +45,10 @@ monster.strategiesTarget = { random = 10, } +monster.events = { + "GlowingRubbishAmuletDeath", +} + monster.flags = { summonable = false, attackable = true, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua index 547c67f7cf1..b854cf01fe6 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_shadow.lua @@ -13,10 +13,6 @@ monster.outfit = { lookMount = 0, } -monster.events = { - "GlowingRubbishAmuletDeath", -} - monster.health = 3000 monster.maxHealth = 3000 monster.race = "blood" @@ -36,6 +32,10 @@ monster.strategiesTarget = { random = 10, } +monster.events = { + "GlowingRubbishAmuletDeath", +} + monster.flags = { summonable = false, attackable = true, diff --git a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_thief.lua b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_thief.lua index 68ed4699b15..a753fcaaab0 100644 --- a/data-otservbr-global/monster/quests/cults_of_tibia/misguided_thief.lua +++ b/data-otservbr-global/monster/quests/cults_of_tibia/misguided_thief.lua @@ -45,6 +45,10 @@ monster.strategiesTarget = { random = 10, } +monster.events = { + "GlowingRubbishAmuletDeath", +} + monster.flags = { summonable = false, attackable = true, diff --git a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua index a381c3b07d6..1a666a75342 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_baron_from_below.lua @@ -151,18 +151,4 @@ monster.immunities = { { 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/monster/quests/dangerous_depth/bosses/the_count_of_the_core.lua b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_count_of_the_core.lua index 17cb6520d29..60769958a14 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_count_of_the_core.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_count_of_the_core.lua @@ -152,18 +152,4 @@ monster.immunities = { { 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/monster/quests/dangerous_depth/bosses/the_duke_of_the_depths.lua b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_duke_of_the_depths.lua index 99053b93882..29f3d1d3e40 100644 --- a/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_duke_of_the_depths.lua +++ b/data-otservbr-global/monster/quests/dangerous_depth/bosses/the_duke_of_the_depths.lua @@ -152,18 +152,4 @@ monster.heals = { { type = COMBAT_FIREDAMAGE, percent = 100 }, } -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/monster/quests/feaster_of_souls/irgix_the_flimsy.lua b/data-otservbr-global/monster/quests/feaster_of_souls/irgix_the_flimsy.lua index 307f1b27380..1d2507cb3e5 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/irgix_the_flimsy.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/irgix_the_flimsy.lua @@ -113,18 +113,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/the_dread_maiden.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua index 83308c9c2fc..9fbbf66ce16 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_dread_maiden.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/the_fear_feaster.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua index 85a6444085b..dda3018993c 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_fear_feaster.lua @@ -136,18 +136,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/the_pale_worm.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua index ab309d2f583..6c816a7ee52 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_pale_worm.lua @@ -144,18 +144,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/the_unwelcome.lua b/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua index e4abf230b1d..a3a283b0a7f 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/the_unwelcome.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/unaz_the_mean.lua b/data-otservbr-global/monster/quests/feaster_of_souls/unaz_the_mean.lua index fb871252bea..52582834231 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/unaz_the_mean.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/unaz_the_mean.lua @@ -113,18 +113,4 @@ monster.immunities = { { 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/monster/quests/feaster_of_souls/vok_the_freakish.lua b/data-otservbr-global/monster/quests/feaster_of_souls/vok_the_freakish.lua index 4efff07d202..7de35d1b9d1 100644 --- a/data-otservbr-global/monster/quests/feaster_of_souls/vok_the_freakish.lua +++ b/data-otservbr-global/monster/quests/feaster_of_souls/vok_the_freakish.lua @@ -111,18 +111,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/ferumbras_mortal_shell.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ferumbras_mortal_shell.lua index 7ad855bc88a..a7c9f071385 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ferumbras_mortal_shell.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ferumbras_mortal_shell.lua @@ -186,18 +186,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/mazoran.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/mazoran.lua index 3f32bac95d4..8213e9a4d51 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/mazoran.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/mazoran.lua @@ -141,18 +141,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/plagirath.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/plagirath.lua index 364b4f864a8..b8fff3b3006 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/plagirath.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/plagirath.lua @@ -141,18 +141,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/ragiaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ragiaz.lua index df016edfd84..856dbf02d2b 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ragiaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/ragiaz.lua @@ -144,18 +144,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/razzagorn.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/razzagorn.lua index 066e22237c0..f95b0b69093 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/razzagorn.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/razzagorn.lua @@ -158,18 +158,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/shulgrax.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/shulgrax.lua index 72c908104af..2168dcc3bf2 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/shulgrax.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/shulgrax.lua @@ -81,7 +81,6 @@ monster.loot = { { id = 6558, chance = 10000 }, -- flask of demonic blood { id = 6558, chance = 10000 }, -- flask of demonic blood { id = 6558, chance = 10000 }, -- flask of demonic blood - { id = 17838, chance = 1800 }, -- unknown item { id = 3019, chance = 1000 }, -- demonbone amulet { id = 3026, chance = 12000, maxCount = 8 }, -- white pearl { id = 3029, chance = 12000, maxCount = 9 }, -- small sapphire @@ -153,18 +152,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/tarbaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/tarbaz.lua index 30b99353cdf..7cb57a1040d 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/tarbaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/tarbaz.lua @@ -143,18 +143,4 @@ monster.immunities = { { 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/monster/quests/ferumbras_ascension/bosses/zamulosh.lua b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/zamulosh.lua index 03fa92d3394..41e8b074228 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/zamulosh.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascension/bosses/zamulosh.lua @@ -143,18 +143,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua index 17d68ca6994..c4228eefe54 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lady_tenebris.lua @@ -149,18 +149,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/lloyd.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua index 5d5f729e749..1f73944519a 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/lloyd.lua @@ -146,18 +146,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua index 6fa44fff690..5f50a0c3e22 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/melting_frozen_horror.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua index 2def55d9283..c45a1fc4ef0 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/soul_of_dragonking_zyrtarch.lua @@ -147,18 +147,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua index fef77ab81cf..e13c2f7fd22 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_blazing_time_guardian.lua @@ -131,18 +131,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua index c664a5e21d2..ab868b6f58c 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_enraged_thorn_knight.lua @@ -152,18 +152,4 @@ monster.heals = { { type = COMBAT_DEATHDAMAGE, percent = 100 }, } -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/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua index 8fcbd1ddbab..b3f64c4331a 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_freezing_time_guardian.lua @@ -132,18 +132,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua index f1d96fe25bc..30dd34b9766 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_last_lore_keeper.lua @@ -164,18 +164,4 @@ monster.immunities = { { 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/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua index 7bf8e0c82ad..902c9a28950 100644 --- a/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua +++ b/data-otservbr-global/monster/quests/forgotten_knowledge/bosses/the_time_guardian.lua @@ -150,18 +150,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/count_vlarkorth.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua index ced550fbc84..f2de105033d 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/count_vlarkorth.lua @@ -142,18 +142,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/duke_krule.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua index 518eda46ac2..851867e0161 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/duke_krule.lua @@ -135,18 +135,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/earl_osam.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua index c996116a336..930a744f326 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/earl_osam.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/king_zelos.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua index cafd09f34a7..b723715c55d 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/king_zelos.lua @@ -122,18 +122,4 @@ monster.voices = { { text = "My lich-knights will conquer this world for me!", yell = 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/monster/quests/grave_danger/bosses/lord_azaram.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua index 8507c3a0c1c..188f11c9dc6 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/lord_azaram.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/scarlett_etzel.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua index 6673313045f..9dcb6503d38 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/scarlett_etzel.lua @@ -146,18 +146,4 @@ monster.immunities = { { 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/monster/quests/grave_danger/bosses/sir_baeloc.lua b/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua index 042ce32e981..957ad10e5ff 100644 --- a/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua +++ b/data-otservbr-global/monster/quests/grave_danger/bosses/sir_baeloc.lua @@ -136,18 +136,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/aftershock.lua b/data-otservbr-global/monster/quests/heart_of_destruction/aftershock.lua index 04c1b3a2589..8f14e9d3fb1 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/aftershock.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/aftershock.lua @@ -106,18 +106,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/anomaly.lua b/data-otservbr-global/monster/quests/heart_of_destruction/anomaly.lua index 2d6c0e44405..6350b49a3c6 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/anomaly.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/anomaly.lua @@ -145,18 +145,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/charged_anomaly.lua b/data-otservbr-global/monster/quests/heart_of_destruction/charged_anomaly.lua index 075c308d7df..aa3f5589fc5 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/charged_anomaly.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/charged_anomaly.lua @@ -103,18 +103,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/charging_outburst.lua b/data-otservbr-global/monster/quests/heart_of_destruction/charging_outburst.lua index 273ab8f579e..d765d016a8a 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/charging_outburst.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/charging_outburst.lua @@ -103,18 +103,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/eradicator.lua b/data-otservbr-global/monster/quests/heart_of_destruction/eradicator.lua index d81c9b4faf1..e7eb2443a4d 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/eradicator.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/eradicator.lua @@ -137,18 +137,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/eradicator2.lua b/data-otservbr-global/monster/quests/heart_of_destruction/eradicator2.lua index 14b92badfbe..0c8dba87dac 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/eradicator2.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/eradicator2.lua @@ -136,18 +136,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/foreshock.lua b/data-otservbr-global/monster/quests/heart_of_destruction/foreshock.lua index 99f5be41e19..7e1f3fc214a 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/foreshock.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/foreshock.lua @@ -106,18 +106,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/outburst.lua b/data-otservbr-global/monster/quests/heart_of_destruction/outburst.lua index c40159545ed..e0efdb42d16 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/outburst.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/outburst.lua @@ -128,18 +128,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/realityquake.lua b/data-otservbr-global/monster/quests/heart_of_destruction/realityquake.lua index c9d7601584f..3870524d5a9 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/realityquake.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/realityquake.lua @@ -127,18 +127,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/rupture.lua b/data-otservbr-global/monster/quests/heart_of_destruction/rupture.lua index 5d68108bba4..672bd5ecc0c 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/rupture.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/rupture.lua @@ -131,18 +131,4 @@ monster.immunities = { { 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/monster/quests/heart_of_destruction/world_devourer.lua b/data-otservbr-global/monster/quests/heart_of_destruction/world_devourer.lua index c8e7198a2e1..6bf55bf348d 100644 --- a/data-otservbr-global/monster/quests/heart_of_destruction/world_devourer.lua +++ b/data-otservbr-global/monster/quests/heart_of_destruction/world_devourer.lua @@ -135,18 +135,4 @@ monster.immunities = { { 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/monster/quests/hero_of_rathleton/deep_terror.lua b/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua index debd09c9bb9..aaa7f1936af 100644 --- a/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua +++ b/data-otservbr-global/monster/quests/hero_of_rathleton/deep_terror.lua @@ -109,18 +109,4 @@ monster.immunities = { { 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/monster/quests/hero_of_rathleton/professor_maxxen.lua b/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua index 947a56a0187..4085e5eab86 100644 --- a/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua +++ b/data-otservbr-global/monster/quests/hero_of_rathleton/professor_maxxen.lua @@ -127,18 +127,4 @@ monster.immunities = { { 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/monster/quests/kilmaresh/bragrumol.lua b/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua index bb7ef950744..125a017735b 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/bragrumol.lua @@ -117,18 +117,4 @@ monster.immunities = { { 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/monster/quests/kilmaresh/mozradek.lua b/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua index 8602923a08b..da498edede4 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/mozradek.lua @@ -111,18 +111,4 @@ monster.immunities = { { 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/monster/quests/kilmaresh/urmahlullu_the_weakened.lua b/data-otservbr-global/monster/quests/kilmaresh/urmahlullu_the_weakened.lua index 96a8dd39081..1060d49b26f 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/urmahlullu_the_weakened.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/urmahlullu_the_weakened.lua @@ -147,18 +147,4 @@ monster.immunities = { { 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/monster/quests/kilmaresh/xogixath.lua b/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua index 3c77465e1ab..70dc531f5ce 100644 --- a/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua +++ b/data-otservbr-global/monster/quests/kilmaresh/xogixath.lua @@ -117,18 +117,4 @@ monster.immunities = { { 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/monster/quests/liquid_black/jaul.lua b/data-otservbr-global/monster/quests/liquid_black/jaul.lua index 965bbacb14c..7802788a73e 100644 --- a/data-otservbr-global/monster/quests/liquid_black/jaul.lua +++ b/data-otservbr-global/monster/quests/liquid_black/jaul.lua @@ -123,18 +123,4 @@ monster.immunities = { { 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/monster/quests/liquid_black/obujos.lua b/data-otservbr-global/monster/quests/liquid_black/obujos.lua index 1f32fd54f1c..5e732cdcbd0 100644 --- a/data-otservbr-global/monster/quests/liquid_black/obujos.lua +++ b/data-otservbr-global/monster/quests/liquid_black/obujos.lua @@ -115,18 +115,4 @@ monster.immunities = { { 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/monster/quests/liquid_black/tanjis.lua b/data-otservbr-global/monster/quests/liquid_black/tanjis.lua index 586af950be3..f726e36fe55 100644 --- a/data-otservbr-global/monster/quests/liquid_black/tanjis.lua +++ b/data-otservbr-global/monster/quests/liquid_black/tanjis.lua @@ -118,18 +118,4 @@ monster.immunities = { { 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/monster/quests/marapur/timira_the_many-headed.lua b/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua index 43d0a1502c3..09ed0f19be8 100644 --- a/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua +++ b/data-otservbr-global/monster/quests/marapur/timira_the_many-headed.lua @@ -125,10 +125,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua index 8f3bf7f6166..9607bf8310c 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/magma_bubble.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/quests/primal_ordeal_quest/plunder_patriarch.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/plunder_patriarch.lua index 25d7c224f09..42fbf1fcdd9 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/plunder_patriarch.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/plunder_patriarch.lua @@ -127,18 +127,4 @@ monster.immunities = { { 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/monster/quests/primal_ordeal_quest/the_primal_menace.lua b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua index 7ad43b016c9..b0ba0ae8686 100644 --- a/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua +++ b/data-otservbr-global/monster/quests/primal_ordeal_quest/the_primal_menace.lua @@ -162,16 +162,6 @@ local function initialize(monster) end -- Functions for the fight -mType.onAppear = function(monster, creature) - if monster:getId() == creature:getId() then - initialize(monster) - end - - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - local function getHazardPoints(monster) local hazard = Hazard.getByName("hazard.gnomprona-gardens") if not hazard then diff --git a/data-otservbr-global/monster/quests/roshamuul/gaz'haragoth.lua b/data-otservbr-global/monster/quests/roshamuul/gaz'haragoth.lua index 0e6d5695d33..6dce4e10838 100644 --- a/data-otservbr-global/monster/quests/roshamuul/gaz'haragoth.lua +++ b/data-otservbr-global/monster/quests/roshamuul/gaz'haragoth.lua @@ -179,18 +179,4 @@ monster.immunities = { { 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/monster/quests/roshamuul/omrafir.lua b/data-otservbr-global/monster/quests/roshamuul/omrafir.lua index e3f09b27dd0..03254912b71 100644 --- a/data-otservbr-global/monster/quests/roshamuul/omrafir.lua +++ b/data-otservbr-global/monster/quests/roshamuul/omrafir.lua @@ -148,18 +148,4 @@ monster.immunities = { { 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/monster/quests/roshamuul/prince_drazzak.lua b/data-otservbr-global/monster/quests/roshamuul/prince_drazzak.lua index f969d02e6aa..d2a65e59fea 100644 --- a/data-otservbr-global/monster/quests/roshamuul/prince_drazzak.lua +++ b/data-otservbr-global/monster/quests/roshamuul/prince_drazzak.lua @@ -126,18 +126,4 @@ monster.immunities = { { 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/monster/quests/soul_war/goshnar's_megalomania_blue.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua index cfd0f53f7fa..cf81168aa00 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_blue.lua @@ -127,12 +127,6 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - local intervalBetweenExecutions = 10000 local zone = Zone.getByName("boss.goshnar's-megalomania-purple") diff --git a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua index 8e8effb5e08..787ab94b662 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnar's_megalomania_green.lua @@ -138,12 +138,6 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - local intervalBetweenExecutions = 10000 local zone = Zone.getByName("boss.goshnar's-megalomania-purple") diff --git a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua index 3f1cb2c4421..468e6a312e4 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_cruelty.lua @@ -144,16 +144,6 @@ mType.onThink = function(monster, interval) end end -mType.onAppear = function(monster, creature) end - -mType.onSpawn = function(monsterCallback) - if monsterCallback:getType():isRewardBoss() then - monsterCallback:setReward(true) - end - - firstTime = 0 -end - mType.onDisappear = function(monster, creature) if creature:getName() == "Goshnar's Cruelty" then local eyeCreature = Creature("A Greedy Eye") @@ -163,8 +153,4 @@ mType.onDisappear = function(monster, creature) end 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/monster/quests/soul_war/goshnars_greed.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua index 16d995988a5..e17e581212e 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_greed.lua @@ -185,8 +185,4 @@ mType.onDisappear = function(monster, creature) end 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/monster/quests/soul_war/goshnars_hatred.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua index f218e0b7e9f..cc6652eb9d9 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_hatred.lua @@ -133,18 +133,6 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onThink = function(monster, interval) end - -mType.onAppear = function(monster, creature) end - -mType.onSpawn = function(monster) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end - - monster:resetHatredDamageMultiplier() -end - mType.onDisappear = function(monster, creature) if creature:getName() == "Goshnar's Hatred" then for _, monsterName in pairs(SoulWarQuest.burningHatredMonsters) do @@ -156,8 +144,4 @@ mType.onDisappear = function(monster, creature) end 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/monster/quests/soul_war/goshnars_malice.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua index c4598e9bbe0..1cda5185bbe 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_malice.lua @@ -147,16 +147,4 @@ mType.onThink = function(monster, interval) end 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/monster/quests/soul_war/goshnars_spite.lua b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua index 7501e466f54..1daedf2a191 100644 --- a/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua +++ b/data-otservbr-global/monster/quests/soul_war/goshnars_spite.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/black_vixen.lua b/data-otservbr-global/monster/quests/the_curse_spreads/black_vixen.lua index 214b8c6f2ce..6f7f41694fe 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/black_vixen.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/black_vixen.lua @@ -138,18 +138,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/bloodback.lua b/data-otservbr-global/monster/quests/the_curse_spreads/bloodback.lua index 3b9dd8e0eea..5423c6e2e9e 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/bloodback.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/bloodback.lua @@ -131,18 +131,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/darkfang.lua b/data-otservbr-global/monster/quests/the_curse_spreads/darkfang.lua index 5506350848b..70b6c25bb1e 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/darkfang.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/darkfang.lua @@ -134,18 +134,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/feroxa5.lua b/data-otservbr-global/monster/quests/the_curse_spreads/feroxa5.lua index 39fed1dc78c..57ccdba515a 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/feroxa5.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/feroxa5.lua @@ -118,18 +118,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/shadowpelt.lua b/data-otservbr-global/monster/quests/the_curse_spreads/shadowpelt.lua index 2b195487dfd..1e28879cd9c 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/shadowpelt.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/shadowpelt.lua @@ -134,18 +134,4 @@ monster.immunities = { { 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/monster/quests/the_curse_spreads/sharpclaw.lua b/data-otservbr-global/monster/quests/the_curse_spreads/sharpclaw.lua index 50ad689b7c7..08f757afcfc 100644 --- a/data-otservbr-global/monster/quests/the_curse_spreads/sharpclaw.lua +++ b/data-otservbr-global/monster/quests/the_curse_spreads/sharpclaw.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/alptramun.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua index 46b5cf6c91d..af8b385ddb2 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/alptramun.lua @@ -150,18 +150,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/faceless_bane.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/faceless_bane.lua index 868fe08e756..f129a99f00a 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/faceless_bane.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/faceless_bane.lua @@ -145,23 +145,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onThink = function(monster, interval) end - -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - -- reset global storage state to default / ensure sqm's reset for the next team - Game.setStorageValue(GlobalStorage.TheDreamCourts.FacelessBane.Deaths, -1) - Game.setStorageValue(GlobalStorage.TheDreamCourts.FacelessBane.StepsOn, -1) - Game.setStorageValue(GlobalStorage.TheDreamCourts.FacelessBane.ResetSteps, 1) - monster:registerEvent("facelessBaneImmunity") - 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/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua index 9c693024899..88688c4fffc 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/izcandar_the_banished.lua @@ -152,18 +152,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua index 2bd63f042be..651ee8cb59b 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/malofur_mangrinder.lua @@ -145,18 +145,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/maxxenius.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua index 8db50108f56..a54257df723 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/maxxenius.lua @@ -152,18 +152,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/plagueroot.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/plagueroot.lua index d62affd19a4..3d5675c4486 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/plagueroot.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/plagueroot.lua @@ -178,18 +178,4 @@ monster.immunities = { { 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/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua index d0520193aad..3937edcd2d4 100644 --- a/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua +++ b/data-otservbr-global/monster/quests/the_dream_courts/bosses/the_nightmare_beast.lua @@ -154,18 +154,4 @@ monster.immunities = { { 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/monster/quests/the_first_dragon/angry_plant.lua b/data-otservbr-global/monster/quests/the_first_dragon/angry_plant.lua index 7ecc32947fb..97f702b6639 100644 --- a/data-otservbr-global/monster/quests/the_first_dragon/angry_plant.lua +++ b/data-otservbr-global/monster/quests/the_first_dragon/angry_plant.lua @@ -20,6 +20,10 @@ monster.corpse = 2983 monster.speed = 55 monster.manaCost = 0 +monster.events = { + "AngryPlantDeath", +} + monster.changeTarget = { interval = 2000, chance = 5, diff --git a/data-otservbr-global/monster/quests/the_first_dragon/bosses/fallen_challenger.lua b/data-otservbr-global/monster/quests/the_first_dragon/bosses/fallen_challenger.lua index 1e050fdfd65..3ac0bb8f18f 100644 --- a/data-otservbr-global/monster/quests/the_first_dragon/bosses/fallen_challenger.lua +++ b/data-otservbr-global/monster/quests/the_first_dragon/bosses/fallen_challenger.lua @@ -20,6 +20,10 @@ monster.corpse = 775 monster.speed = 150 monster.manaCost = 0 +monster.events = { + "FallenDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_first_dragon/dragon_essence.lua b/data-otservbr-global/monster/quests/the_first_dragon/dragon_essence.lua index 629b187cf93..a91ecae04c5 100644 --- a/data-otservbr-global/monster/quests/the_first_dragon/dragon_essence.lua +++ b/data-otservbr-global/monster/quests/the_first_dragon/dragon_essence.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 125 monster.manaCost = 0 +monster.events = { + "DragonEssenceDeath", +} + monster.changeTarget = { interval = 2000, chance = 5, diff --git a/data-otservbr-global/monster/quests/the_first_dragon/somewhat_beatable.lua b/data-otservbr-global/monster/quests/the_first_dragon/somewhat_beatable.lua index 8829b1415d9..9c0ace92c1f 100644 --- a/data-otservbr-global/monster/quests/the_first_dragon/somewhat_beatable.lua +++ b/data-otservbr-global/monster/quests/the_first_dragon/somewhat_beatable.lua @@ -53,7 +53,7 @@ monster.flags = { } monster.events = { - "Somewhat Beatable Death", + "SomewhatBeatableDeath", } monster.light = { diff --git a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/ancient_lion_knight.lua b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/ancient_lion_knight.lua index aba0cc866b4..3f5ad2a3cd7 100644 --- a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/ancient_lion_knight.lua +++ b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/ancient_lion_knight.lua @@ -131,10 +131,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua index 9d86b77cd48..34d15a0a248 100644 --- a/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua +++ b/data-otservbr-global/monster/quests/the_order_of_lion/bosses/drume.lua @@ -161,10 +161,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster:getType():isRewardBoss() then - monster:setReward(true) - end -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/the_order_of_lion/lion_commander.lua b/data-otservbr-global/monster/quests/the_order_of_lion/lion_commander.lua index f409fca3c4b..378bbc0e1a5 100644 --- a/data-otservbr-global/monster/quests/the_order_of_lion/lion_commander.lua +++ b/data-otservbr-global/monster/quests/the_order_of_lion/lion_commander.lua @@ -111,19 +111,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster ~= creature then - return true - end - for i = 1, 5 do - local sum = Game.createMonster(monster:getType():getSummonList()[math.random(1, #monster:getType():getSummonList())].name, monster:getPosition(), true) - if sum then - monster:setSummon(sum) - sum:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - sum:setStorageValue(Storage.TheOrderOfTheLion.Drume.Commander, 1) - end - end - monster:setStorageValue(Storage.TheOrderOfTheLion.Drume.Commander, 1) -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/the_order_of_lion/usurper_commander.lua b/data-otservbr-global/monster/quests/the_order_of_lion/usurper_commander.lua index fd31fa62806..f46ff987e92 100644 --- a/data-otservbr-global/monster/quests/the_order_of_lion/usurper_commander.lua +++ b/data-otservbr-global/monster/quests/the_order_of_lion/usurper_commander.lua @@ -112,20 +112,4 @@ monster.immunities = { { type = "bleed", condition = false }, } -mType.onAppear = function(monster, creature) - if monster ~= creature then - return true - end - local sum - for i = 1, 5 do - sum = Game.createMonster(monster:getType():getSummonList()[math.random(1, #monster:getType():getSummonList())].name, monster:getPosition(), true) - if sum then - monster:setSummon(sum) - sum:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - sum:setStorageValue(Storage.TheOrderOfTheLion.Drume.Commander, 1) - end - end - monster:setStorageValue(Storage.TheOrderOfTheLion.Drume.Commander, 1) -end - mType:register(monster) diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/brokul.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/brokul.lua index 727249e61d0..f05a8adae85 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/brokul.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/brokul.lua @@ -25,6 +25,10 @@ monster.corpse = 28635 monster.speed = 105 monster.manaCost = 0 +monster.events = { + "killingLibrary", +} + monster.changeTarget = { interval = 1000, chance = 10, @@ -125,18 +129,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/ghulosh.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua index 09d4abb0935..fe80352ff13 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/ghulosh.lua @@ -14,7 +14,7 @@ monster.outfit = { } monster.events = { - "SecretLibraryBossDeath", + "ghuloshThink", } monster.bosstiary = { @@ -95,7 +95,6 @@ monster.loot = { { name = "butcher's axe", chance = 1000 }, { name = "dreaded cleaver", chance = 1000 }, { name = "mercenary sword", chance = 1000 }, - { id = 28341, chance = 1000 }, -- tessellated wall { name = "slightly rusted shield", chance = 5880 }, { name = "slightly rusted helmet", chance = 35290 }, { name = "epaulette", chance = 500 }, @@ -137,18 +136,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/gorzindel.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua index e5a1e3d6424..7a31d798d9a 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/gorzindel.lua @@ -14,7 +14,7 @@ monster.outfit = { } monster.events = { - "SecretLibraryBossDeath", + "gorzindelHealth", } monster.bosstiary = { @@ -143,18 +143,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/grand_canon_dominus.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_canon_dominus.lua index f6976c6d732..453c3be3389 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_canon_dominus.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_canon_dominus.lua @@ -26,7 +26,7 @@ monster.speed = 105 monster.manaCost = 0 monster.events = { - "GrandCanonDominusDeath", + "killingLibrary", } monster.changeTarget = { @@ -119,18 +119,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/grand_chaplain_gaunder.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_chaplain_gaunder.lua index a4d42046c58..f27050df438 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_chaplain_gaunder.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_chaplain_gaunder.lua @@ -26,7 +26,7 @@ monster.speed = 105 monster.manaCost = 0 monster.events = { - "GrandChaplainGaunderDeath", + "killingLibrary", } monster.changeTarget = { @@ -126,18 +126,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/grand_commander_soeren.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_commander_soeren.lua index e79984a5317..bb01cf3c515 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_commander_soeren.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_commander_soeren.lua @@ -26,7 +26,7 @@ monster.speed = 105 monster.manaCost = 0 monster.events = { - "GrandCommanderSoerenDeath", + "killingLibrary", } monster.changeTarget = { @@ -118,18 +118,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/grand_master_oberon.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon.lua index dc5121d128a..5de851ac4c1 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/grand_master_oberon.lua @@ -25,6 +25,11 @@ monster.corpse = 28625 monster.speed = 115 monster.manaCost = 0 +monster.events = { + "killingLibrary", + "oberonImmune", +} + monster.changeTarget = { interval = 4000, chance = 10, @@ -126,20 +131,6 @@ mType.onThink = function(monster, interval) end end -mType.onAppear = function(monster, creature) - if monster:getId() == creature:getId() then - monster:setStorageValue(GrandMasterOberonConfig.Storage.Asking, 1) - monster:setStorageValue(GrandMasterOberonConfig.Storage.Life, 1) - end - 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) if type ~= TALKTYPE_SAY then return false diff --git a/data-otservbr-global/monster/quests/the_secret_library/bosses/preceptor_lazare.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/preceptor_lazare.lua index 64dddc6adf2..f5477192be6 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/preceptor_lazare.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/preceptor_lazare.lua @@ -26,7 +26,7 @@ monster.speed = 105 monster.manaCost = 0 monster.events = { - "PreceptorLazareDeath", + "killingLibrary", } monster.changeTarget = { @@ -130,18 +130,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/thawing_dragon_lord.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/thawing_dragon_lord.lua index fa175a85a2b..ad7e340ffb2 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/thawing_dragon_lord.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/thawing_dragon_lord.lua @@ -105,18 +105,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua b/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua index 491b946adba..2d0e1069f30 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/bosses/the_scourge_of_oblivion.lua @@ -183,18 +183,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/concentrated_death.lua b/data-otservbr-global/monster/quests/the_secret_library/concentrated_death.lua index d83987622d8..fb7ce671970 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/concentrated_death.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/concentrated_death.lua @@ -20,6 +20,10 @@ monster.corpse = 28601 monster.speed = 175 monster.manaCost = 0 +monster.events = { + "ghuloshDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/dazed_leaf_golem.lua b/data-otservbr-global/monster/quests/the_secret_library/dazed_leaf_golem.lua index 06961bae6cd..03c34c04c65 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/dazed_leaf_golem.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/dazed_leaf_golem.lua @@ -21,7 +21,7 @@ monster.speed = 175 monster.manaCost = 0 monster.events = { - "DazedLeafGolemDeath", + "killingLibrary", } monster.changeTarget = { diff --git a/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua b/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua index 621717cd277..8ef0357fca8 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/lokathmor.lua @@ -14,7 +14,7 @@ monster.outfit = { } monster.events = { - "SecretLibraryBossDeath", + "lokathmorDeath", } monster.bosstiary = { @@ -100,7 +100,6 @@ monster.loot = { { name = "dreaded cleaver", chance = 30000 }, { name = "slightly rusted shield", chance = 26670 }, { name = "wand of inferno", chance = 30000 }, - { id = 28341, chance = 1000 }, -- tessellated wall { name = "sturdy book", chance = 1000 }, } @@ -140,18 +139,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/mazzinor.lua b/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua index b5521c45429..f93e6785563 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/mazzinor.lua @@ -14,7 +14,8 @@ monster.outfit = { } monster.events = { - "SecretLibraryBossDeath", + "mazzinorDeath", + "mazzinorHealth", } monster.bosstiary = { @@ -128,18 +129,4 @@ monster.immunities = { { 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/monster/quests/the_secret_library/stolen_knowledge_of_armor.lua b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_armor.lua index 1905e8a29a9..6397d663071 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_armor.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_armor.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 75 monster.manaCost = 0 +monster.events = { + "gorzindelDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_healing.lua b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_healing.lua index ffe609dc45a..84c63db20ce 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_healing.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_healing.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 75 monster.manaCost = 0 +monster.events = { + "gorzindelDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_lifesteal.lua b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_lifesteal.lua index ec3ccaefa97..f93849fbbde 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_lifesteal.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_lifesteal.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 75 monster.manaCost = 0 +monster.events = { + "gorzindelDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_spells.lua b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_spells.lua index 58fff59a202..bdbe4118398 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_spells.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_spells.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 75 monster.manaCost = 0 +monster.events = { + "gorzindelDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_summoning.lua b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_summoning.lua index 87c05596b01..ecd11fc0b46 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_summoning.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/stolen_knowledge_of_summoning.lua @@ -20,6 +20,10 @@ monster.corpse = 0 monster.speed = 75 monster.manaCost = 0 +monster.events = { + "gorzindelDeath", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/the_blazing_rose.lua b/data-otservbr-global/monster/quests/the_secret_library/the_blazing_rose.lua index 3eb95e76a26..569c69affe7 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/the_blazing_rose.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/the_blazing_rose.lua @@ -25,6 +25,10 @@ monster.corpse = 28794 monster.speed = 175 monster.manaCost = 0 +monster.events = { + "AsurasMechanic", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/the_diamond_blossom.lua b/data-otservbr-global/monster/quests/the_secret_library/the_diamond_blossom.lua index 03fc38bffc8..99dd4fd9d33 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/the_diamond_blossom.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/the_diamond_blossom.lua @@ -25,6 +25,10 @@ monster.corpse = 28802 monster.speed = 175 monster.manaCost = 0 +monster.events = { + "AsurasMechanic", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/quests/the_secret_library/the_lily_of_night.lua b/data-otservbr-global/monster/quests/the_secret_library/the_lily_of_night.lua index 9bf43393315..5b147dee5ed 100644 --- a/data-otservbr-global/monster/quests/the_secret_library/the_lily_of_night.lua +++ b/data-otservbr-global/monster/quests/the_secret_library/the_lily_of_night.lua @@ -25,6 +25,10 @@ monster.corpse = 28802 monster.speed = 175 monster.manaCost = 0 +monster.events = { + "AsurasMechanic", +} + monster.changeTarget = { interval = 5000, chance = 8, diff --git a/data-otservbr-global/monster/raids/chayenne.lua b/data-otservbr-global/monster/raids/chayenne.lua index 0f8f64d9686..2ab96a01c2d 100644 --- a/data-otservbr-global/monster/raids/chayenne.lua +++ b/data-otservbr-global/monster/raids/chayenne.lua @@ -105,18 +105,4 @@ monster.immunities = { { 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/monster/raids/chizzoron_the_distorter.lua b/data-otservbr-global/monster/raids/chizzoron_the_distorter.lua index 7fbc5d3cd71..3569332eaf2 100644 --- a/data-otservbr-global/monster/raids/chizzoron_the_distorter.lua +++ b/data-otservbr-global/monster/raids/chizzoron_the_distorter.lua @@ -123,18 +123,4 @@ monster.immunities = { { 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/monster/raids/ferumbras.lua b/data-otservbr-global/monster/raids/ferumbras.lua index c3dfea647ea..f49eb8075ab 100644 --- a/data-otservbr-global/monster/raids/ferumbras.lua +++ b/data-otservbr-global/monster/raids/ferumbras.lua @@ -168,18 +168,4 @@ monster.immunities = { { 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/monster/raids/furyosa.lua b/data-otservbr-global/monster/raids/furyosa.lua index acbf9711298..bc4ffdc3477 100644 --- a/data-otservbr-global/monster/raids/furyosa.lua +++ b/data-otservbr-global/monster/raids/furyosa.lua @@ -133,18 +133,4 @@ monster.immunities = { { 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/monster/raids/ghazbaran.lua b/data-otservbr-global/monster/raids/ghazbaran.lua index 5f57655679f..f014e06e82a 100644 --- a/data-otservbr-global/monster/raids/ghazbaran.lua +++ b/data-otservbr-global/monster/raids/ghazbaran.lua @@ -164,18 +164,4 @@ monster.immunities = { { 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/monster/raids/glooth_bomb.lua b/data-otservbr-global/monster/raids/glooth_bomb.lua index b1973e7b8ec..a69c59a3c6c 100644 --- a/data-otservbr-global/monster/raids/glooth_bomb.lua +++ b/data-otservbr-global/monster/raids/glooth_bomb.lua @@ -114,18 +114,4 @@ monster.immunities = { { 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/monster/raids/hirintror.lua b/data-otservbr-global/monster/raids/hirintror.lua index 12a4d20d183..aa3ac63011d 100644 --- a/data-otservbr-global/monster/raids/hirintror.lua +++ b/data-otservbr-global/monster/raids/hirintror.lua @@ -125,18 +125,4 @@ monster.immunities = { { 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/monster/raids/mawhawk.lua b/data-otservbr-global/monster/raids/mawhawk.lua index f00407ca304..697638fdda4 100644 --- a/data-otservbr-global/monster/raids/mawhawk.lua +++ b/data-otservbr-global/monster/raids/mawhawk.lua @@ -121,18 +121,4 @@ monster.immunities = { { 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/monster/raids/morgaroth.lua b/data-otservbr-global/monster/raids/morgaroth.lua index 2e965cc99ec..02a65453da4 100644 --- a/data-otservbr-global/monster/raids/morgaroth.lua +++ b/data-otservbr-global/monster/raids/morgaroth.lua @@ -178,18 +178,4 @@ monster.immunities = { { 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/monster/raids/ocyakao.lua b/data-otservbr-global/monster/raids/ocyakao.lua index 2e036c0837b..5321a0b59ff 100644 --- a/data-otservbr-global/monster/raids/ocyakao.lua +++ b/data-otservbr-global/monster/raids/ocyakao.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/raids/orshabaal.lua b/data-otservbr-global/monster/raids/orshabaal.lua index 7d7ef6052df..2054c1e2a3b 100644 --- a/data-otservbr-global/monster/raids/orshabaal.lua +++ b/data-otservbr-global/monster/raids/orshabaal.lua @@ -167,18 +167,4 @@ monster.immunities = { { 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/monster/raids/the_pale_count.lua b/data-otservbr-global/monster/raids/the_pale_count.lua index 31a40bcfff2..29f1cf6b043 100644 --- a/data-otservbr-global/monster/raids/the_pale_count.lua +++ b/data-otservbr-global/monster/raids/the_pale_count.lua @@ -144,18 +144,4 @@ monster.immunities = { { 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/monster/raids/the_welter.lua b/data-otservbr-global/monster/raids/the_welter.lua index addb7008d75..7e2f2c3ed8f 100644 --- a/data-otservbr-global/monster/raids/the_welter.lua +++ b/data-otservbr-global/monster/raids/the_welter.lua @@ -137,18 +137,4 @@ monster.immunities = { { 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/monster/raids/tyrn.lua b/data-otservbr-global/monster/raids/tyrn.lua index 0c19ac9944f..158a4e93833 100644 --- a/data-otservbr-global/monster/raids/tyrn.lua +++ b/data-otservbr-global/monster/raids/tyrn.lua @@ -131,18 +131,4 @@ monster.immunities = { { 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/monster/raids/white_pale.lua b/data-otservbr-global/monster/raids/white_pale.lua index 06b6dcab4f3..17d093fb5bf 100644 --- a/data-otservbr-global/monster/raids/white_pale.lua +++ b/data-otservbr-global/monster/raids/white_pale.lua @@ -116,18 +116,4 @@ monster.immunities = { { 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/monster/raids/zulazza_the_corruptor.lua b/data-otservbr-global/monster/raids/zulazza_the_corruptor.lua index b7d14d9c966..0c2212c2a45 100644 --- a/data-otservbr-global/monster/raids/zulazza_the_corruptor.lua +++ b/data-otservbr-global/monster/raids/zulazza_the_corruptor.lua @@ -132,18 +132,4 @@ monster.immunities = { { 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/monster/undeads/ahau.lua b/data-otservbr-global/monster/undeads/ahau.lua index 9d7f0f17c9c..ce5704769a9 100644 --- a/data-otservbr-global/monster/undeads/ahau.lua +++ b/data-otservbr-global/monster/undeads/ahau.lua @@ -130,18 +130,4 @@ monster.immunities = { { 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/npc/a_dragon_mother.lua b/data-otservbr-global/npc/a_dragon_mother.lua index ec4653828c6..cfb788c6902 100644 --- a/data-otservbr-global/npc/a_dragon_mother.lua +++ b/data-otservbr-global/npc/a_dragon_mother.lua @@ -54,16 +54,16 @@ local function greetCallback(npc, creature) local player = Player(creature) local playerId = player:getId() - if player:getStorageValue(Storage.ForgottenKnowledge.BabyDragon) < 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BabyDragon) < 1 then npcHandler:setMessage(MESSAGE_GREET, "Greetings humans! Consider yourselfs lucky, I'm in need of {help}.") npcHandler:setTopic(playerId, 1) return true - elseif player:getStorageValue(Storage.ForgottenKnowledge.AccessMachine) == 1 then + elseif player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessMachine) == 1 then npcHandler:setMessage(MESSAGE_GREET, "Grrr.") return true - elseif player:getStorageValue(Storage.ForgottenKnowledge.HorrorKilled) >= 1 then + elseif player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.HorrorKilled) >= 1 then npcHandler:setMessage(MESSAGE_GREET, "You have done me a favour and the knowledge you are seeking shall be yours. I melted the ice for you, you can pass now.") - player:setStorageValue(Storage.ForgottenKnowledge.AccessMachine, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessMachine, 1) end return true end @@ -95,7 +95,7 @@ local function creatureSayCallback(npc, creature, type, message) "So return to the upper tunnels where cultists and ice golems dwell. Somewhere in these tunnels you will find a small prison haunted by a ghost. South of this prison cell there is a tunnel that will lead you eastwards. ...", "Follow the tunnel until you reach a small cave. Step down and down until you see a blue energy field. It will lead you to my egg. It is sealed so that not everyone may enter the room. But you have the permission now.", }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.BabyDragon, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BabyDragon, 1) npcHandler:setTopic(playerId, 4) end elseif MsgContains(message, "no") then @@ -113,7 +113,7 @@ local function creatureSayCallback(npc, creature, type, message) "As I told you, fiendish ice creatures dragged my egg into the lower caves. ...", " Without enough heat the egg will die soon. Venture there and save my hatchling and the knowledge you seeek shall be yours!", }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.BabyDragon, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BabyDragon, 1) end end return true diff --git a/data-otservbr-global/npc/a_strange_chalice.lua b/data-otservbr-global/npc/a_strange_chalice.lua index 4b1c8f1d701..c0523cb09e3 100644 --- a/data-otservbr-global/npc/a_strange_chalice.lua +++ b/data-otservbr-global/npc/a_strange_chalice.lua @@ -57,10 +57,8 @@ local function creatureSayCallback(npc, creature, type, message) return false end - if MsgContains(message, "chalice") and player:getStorageValue(Storage.ForgottenKnowledge.Chalice) == 1 then - npcHandler:say({ - "Finally. That's what I... oh wait, you're still talking to me - you will blow my cover! What do you want? Oh wait, did my {daughter} send you? It has been some time now, indeed.", - }, npc, creature) + if MsgContains(message, "chalice") and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Chalice) == 1 then + npcHandler:say("Finally. That's what I... oh wait, you're still talking to me - you will blow my cover! What do you want? Oh wait, did my {daughter} send you? It has been some time now, indeed.", npc, creature) npcHandler:setTopic(playerId, 1) end @@ -111,11 +109,13 @@ local function creatureSayCallback(npc, creature, type, message) " I already know how to enter it, you need to step in and yell 'zzubaran'. Unfortunately they never took me with them. ...", " I heard them say it once, when a seemingly drunk guard yelled it in front of a wall mounted torch, hitting his head against it afterwards. He spilt all my contents on the floor, hmpf.", }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessLavaTeleport, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessLavaTeleport, 1) end return true end +npcHandler:setMessage(MESSAGE_GREET, "Hi? What do you mean 'hi' - can't you see I am a... I have to lower my voice. Did it occur to you, that this 'chalice' does not want to be disturbed?! Leave me alone!") + npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/a_weakened_forest_fury.lua b/data-otservbr-global/npc/a_weakened_forest_fury.lua index 1d9a8a4ccdc..3bd1cdc49f2 100644 --- a/data-otservbr-global/npc/a_weakened_forest_fury.lua +++ b/data-otservbr-global/npc/a_weakened_forest_fury.lua @@ -50,13 +50,6 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end --- Don't forget npcHandler = npcHandler in the parameters. It is required for all StdModule functions! -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = " My name is now known only to the wind and it shall remain like this until I will return to my kin." }) -keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I was a guardian of this glade. I am the last one... everyone had to leave." }) -keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "This glade's time is growing short if nothing will be done soon." }) -keywordHandler:addKeyword({ "forest fury" }, StdModule.say, { npcHandler = npcHandler, text = "Take care, guardian." }) -keywordHandler:addKeyword({ "orclops" }, StdModule.say, { npcHandler = npcHandler, text = "Cruel beings. Large and monstrous, with a single eye, staring at their prey. " }) - local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -81,59 +74,62 @@ local function creatureSayCallback(npc, creature, type, message) "Indeed, you will. Take one of these cages, which have been crafted generations ago to rob a creature of its freedom for that it may earn it again truthfully. Return the birds back to their home in the glade. ...", "You will find {phials} for water near this sacred well which will take you safely to the glade. No seeds are left, they are in the hands of the intruders now. Have faith in yourself, guardian.", }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.BirdCage, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCage, 1) player:addItem(23812, 1) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "seeds") then if npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "Seeds to give life to strong trees, blooming and proud. The {intruders} robbed us from them.", - }, npc, creature) + npcHandler:say("Seeds to give life to strong trees, blooming and proud. The {intruders} robbed us from them.", npc, creature) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "intruders") then if npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "The intruders appeared in the blink of an eye. Out of thin air, as if they came from nowhere. They overrun the glade within ours and drove away what was remaining from us within the day.", - }, npc, creature) + npcHandler:say("The intruders appeared in the blink of an eye. Out of thin air, as if they came from nowhere. They overrun the glade within ours and drove away what was remaining from us within the day.", npc, creature) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "water") then if npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "The purest water flows through this well. For centuries we concealed it, for other beings to not lay their eyes on it.", - }, npc, creature) + npcHandler:say("The purest water flows through this well. For centuries we concealed it, for other beings to not lay their eyes on it.", npc, creature) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "birds") then if npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "Take care, guardian.", - }, npc, creature) + npcHandler:say("Take care, guardian.", npc, creature) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "phials") then if npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "Phials for the purest water from our sacred well. They are finely crafted and very fragile. We keep a small supply up here around the well. Probably the only thing the intruders did not care for.", - }, npc, creature) + npcHandler:say("Phials for the purest water from our sacred well. They are finely crafted and very fragile. We keep a small supply up here around the well. Probably the only thing the intruders did not care for.", npc, creature) + npcHandler:setTopic(playerId, 0) end - end - if MsgContains(message, "cages") and player:getStorageValue(Storage.ForgottenKnowledge.BirdCage) == 1 then + elseif MsgContains(message, "cages") and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCage) == 1 then npcHandler:say({ "Crafted generations ago to rob a creature of its freedom for that it may earn it again truthfully. You will need them if you plan on returning the birds to their rightful home in the glade. ... ", "Are you in need of another one? ", }, npc, creature) npcHandler:setTopic(playerId, 2) - end - if MsgContains(message, "yes") then + elseif MsgContains(message, "yes") then if npcHandler:getTopic(playerId) == 2 then - npcHandler:say({ - "I already handed a cage to you. If you are in need of another one, you will have to return to me later.", - }, npc, creature) + npcHandler:say("I already handed a cage to you. If you are in need of another one, you will have to return to me later.", npc, creature) + npcHandler:setTopic(playerId, 0) end end + return true end -npcHandler:setCallback(CALLBACK_GREET, greetCallback) +npcHandler:setMessage(MESSAGE_GREET, "I greet you, human. This is a time of distress, more than ever are we in need of guardians to protect us and our world.") + npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + +-- Don't forget npcHandler = npcHandler in the parameters. It is required for all StdModule functions! +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "My name is now known only to the wind and it shall remain like this until I will return to my kin." }) +keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I was a guardian of this glade. I am the last one... everyone had to leave." }) +keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "This glade's time is growing short if nothing will be done soon." }) +keywordHandler:addKeyword({ "forest fury" }, StdModule.say, { npcHandler = npcHandler, text = "Take care, guardian." }) +keywordHandler:addKeyword({ "orclops" }, StdModule.say, { npcHandler = npcHandler, text = "Cruel beings. Large and monstrous, with a single eye, staring at their prey. " }) + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) -- npcType registering the npcConfig table diff --git a/data-otservbr-global/npc/ahmet.lua b/data-otservbr-global/npc/ahmet.lua index 1e1795f6af9..2720daea276 100644 --- a/data-otservbr-global/npc/ahmet.lua +++ b/data-otservbr-global/npc/ahmet.lua @@ -179,7 +179,7 @@ local function creatureSayCallback(npc, creature, type, message) return true end -npcHandler:setMessage(MESSAGE_GREET, "Be mourned pilgrim in flesh. I'm selling general goods.") +npcHandler:setMessage(MESSAGE_GREET, "Be mourned pilgrim in flesh. I'm selling general goods. Just ask me for a {trade}.") npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) diff --git a/data-otservbr-global/npc/albinius.lua b/data-otservbr-global/npc/albinius.lua index ca04c785848..57106ef9df0 100644 --- a/data-otservbr-global/npc/albinius.lua +++ b/data-otservbr-global/npc/albinius.lua @@ -61,10 +61,6 @@ npcType.onThink = function(npc, interval) npcHandler:onThink(npc, interval) end -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "I am Albinius, a worshipper of the {Astral Shapers}." }) -keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "Precisely time." }) -keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I find ways to unveil the secrets of the stars. Judging by this question, I doubt you follow my weekly publications concerning this research." }) - local runes = { { runeid = 24954 }, { runeid = 24955 }, @@ -97,20 +93,18 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "temple") then - npcHandler:say({ - "The temple has been restored to its former glory, yet we strife to live and praise in the {Shaper} ways. Do you still need me to take some old {tomes} from you my child?", - }, npc, creature) + npcHandler:say("The temple has been restored to its former glory, yet we strife to live and praise in the {Shaper} ways. Do you still need me to take some old {tomes} from you my child?", npc, creature) npcHandler:setTopic(playerId, 1) end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 then npcHandler:say("You already offered enough tomes for us to study and rebuild this temple. Thank you, my child.", npc, creature) npcHandler:setTopic(playerId, 0) else if player:getItemCount(23986) >= 5 then player:removeItem(23986, 5) npcHandler:say("Thank you very much for your contribution, child. Your first step in the ways of the {Shapers} has been taken.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.Tomes, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes, 1) else npcHandler:say("You need 5 heavy old tome.", npc, creature) end @@ -120,10 +114,8 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:removeInteraction(npc, creature) end - if MsgContains(message, "tomes") and player:getStorageValue(Storage.ForgottenKnowledge.Tomes) < 1 then - npcHandler:say({ - "If you have some old shaper tomes I would {buy} them.", - }, npc, creature) + if MsgContains(message, "tomes") and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) < 1 then + npcHandler:say("If you have some old shaper tomes I would {buy} them.", npc, creature) npcHandler:setTopic(playerId, 7) end @@ -134,7 +126,7 @@ local function creatureSayCallback(npc, creature, type, message) --- ##Astral Shaper Rune## if MsgContains(message, "astral shaper rune") then - if player:getStorageValue(Storage.ForgottenKnowledge.LastLoreKilled) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LastLoreKilled) >= 1 then npcHandler:say("Do you wish to merge your rune parts into an astral shaper rune?", npc, creature) npcHandler:setTopic(playerId, 8) else @@ -162,21 +154,19 @@ local function creatureSayCallback(npc, creature, type, message) --- ####PORTALS### -- Ice Portal if MsgContains(message, "ice portal") then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then - npcHandler:say({ - "You may pass this portal if you have 50 fish as offering. Do you have the fish with you?", - }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 and player:getStorageValue(Storage.Quest.U8_0.TheIceIslands.FormorgarMinesDoor) == 1 then + npcHandler:say("You may pass this portal if you have 50 fish as offering. Do you have the fish with you?", npc, creature) npcHandler:setTopic(playerId, 2) else - npcHandler:say("Sorry, first you need to bring my Heavy Old Tomes.", npc, creature) + npcHandler:say("Sorry, you first need to bring my Heavy Old Tomes or do the quest before continuing.", npc, creature) end end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 2 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessIce) < 1 and player:getItemCount(3578) >= 50 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessIce) < 1 and player:getItemCount(3578) >= 50 then player:removeItem(3578, 50) npcHandler:say("Thank you for your offering. You may pass the Portal to the Powers of Ice now.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessIce, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessIce, 1) else npcHandler:say("I'm sorry, you don't have enough fish. Return if you can offer fifty of them.", npc, creature) end @@ -186,10 +176,8 @@ local function creatureSayCallback(npc, creature, type, message) -- Holy Portal if MsgContains(message, "holy portal") then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then - npcHandler:say({ - "You may pass this portal if you have 50 incantation notes as offering. Do you have the incantation notes with you?", - }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 then + npcHandler:say("You may pass this portal if you have 50 incantation notes as offering. Do you have the incantation notes with you?", npc, creature) npcHandler:setTopic(playerId, 3) else npcHandler:say("Sorry, first you need to bring my Heavy Old Tomes.", npc, creature) @@ -197,10 +185,10 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 3 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessGolden) < 1 and player:getItemCount(18929) >= 50 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessGolden) < 1 and player:getItemCount(18929) >= 50 then player:removeItem(18929, 50) npcHandler:say("Thank you for your offering. You may pass the Portal to the Powers of Holy now.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessGolden, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessGolden, 1) else npcHandler:say("I'm sorry, you don't have enough incantation notes. Return if you can offer fifty of them.", npc, creature) end @@ -210,10 +198,8 @@ local function creatureSayCallback(npc, creature, type, message) -- Energy Portal if MsgContains(message, "energy portal") then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then - npcHandler:say({ - "You may pass this portal if you have 50 marsh stalker feathers as offering. Do you have the marsh stalker feathers with you?", - }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 then + npcHandler:say("You may pass this portal if you have 50 marsh stalker feathers as offering. Do you have the marsh stalker feathers with you?", npc, creature) npcHandler:setTopic(playerId, 4) else npcHandler:say("Sorry, first you need to bring my Heavy Old Tomes.", npc, creature) @@ -221,10 +207,10 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 4 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessViolet) < 1 and player:getItemCount(17462) >= 50 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessViolet) < 1 and player:getItemCount(17462) >= 50 then player:removeItem(17462, 50) npcHandler:say("Thank you for your offering. You may pass the Portal to the Powers of Energy now.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessViolet, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessViolet, 1) else npcHandler:say("I'm sorry, you don't have enough marsh stalker feathers. Return if you can offer fifty of them.", npc, creature) end @@ -234,10 +220,8 @@ local function creatureSayCallback(npc, creature, type, message) -- Earth Portal if MsgContains(message, "earth portal") then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then - npcHandler:say({ - "You may pass this portal if you have 50 acorns as offering. Do you have the acorns with you?", - }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 then + npcHandler:say("You may pass this portal if you have 50 acorns as offering. Do you have the acorns with you?", npc, creature) npcHandler:setTopic(playerId, 5) else npcHandler:say("Sorry, first you need to bring my Heavy Old Tomes.", npc, creature) @@ -245,10 +229,10 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 5 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessEarth) < 1 and player:getItemCount(10296) >= 50 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessEarth) < 1 and player:getItemCount(10296) >= 50 then player:removeItem(10296, 50) npcHandler:say("Thank you for your offering. You may pass the Portal to the Powers of Earth now.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessEarth, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessEarth, 1) else npcHandler:say("I'm sorry, you don't have enough acorns. Return if you can offer fifty of them.", npc, creature) end @@ -258,10 +242,8 @@ local function creatureSayCallback(npc, creature, type, message) -- Death Portal if MsgContains(message, "death portal") then - if player:getStorageValue(Storage.ForgottenKnowledge.Tomes) == 1 then - npcHandler:say({ - "You may pass this portal if you have 50 pelvis bones as offering. Do you have the pelvis bones with you?", - }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) == 1 then + npcHandler:say("You may pass this portal if you have 50 pelvis bones as offering. Do you have the pelvis bones with you?", npc, creature) npcHandler:setTopic(playerId, 6) else npcHandler:say("Sorry, first you need to bring my Heavy Old Tomes.", npc, creature) @@ -269,10 +251,10 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 6 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessDeath) < 1 and player:getItemCount(11481) >= 50 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessDeath) < 1 and player:getItemCount(11481) >= 50 then player:removeItem(11481, 50) npcHandler:say("Thank you for your offering. You may pass the Portal to the Powers of Death now.", npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessDeath, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessDeath, 1) else npcHandler:say("I'm sorry, you don't have enough pelvis bones. Return if you can offer fifty of them.", npc, creature) end @@ -286,6 +268,11 @@ npcHandler:setMessage(MESSAGE_GREET, "Greetings, pilgrim. Welcome to the halls o npcHandler:setMessage(MESSAGE_WALKAWAY, "Oh... farewell, child.") npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "I am Albinius, a worshipper of the {Astral Shapers}." }) +keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "Precisely time." }) +keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I find ways to unveil the secrets of the stars. Judging by this question, I doubt you follow my weekly publications concerning this research." }) + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/alkestios.lua b/data-otservbr-global/npc/alkestios.lua index 4b7e593316d..00794577cf1 100644 --- a/data-otservbr-global/npc/alkestios.lua +++ b/data-otservbr-global/npc/alkestios.lua @@ -61,13 +61,9 @@ local function creatureSayCallback(npc, creature, type, message) if MsgContains(message, "mission") then if player:getStorageValue(ThreatenedDreams.Mission01[1]) == 1 and player:getStorageValue(ThreatenedDreams.Mission01.PoacherChest) == 1 then - npcHandler:say({ - "Uhmn.. Maybe Ahmet in Ankrahmun can help we to fake this book.", - }, npc, creature) + npcHandler:say("Uhmn.. Maybe Ahmet in Ankrahmun can help we to fake this book.", npc, creature) elseif player:getStorageValue(ThreatenedDreams.Mission01[1]) == 2 then - npcHandler:say({ - "The poachers are still chasing me. Please hurry and find a way to help me.", - }, npc, creature) + npcHandler:say("The poachers are still chasing me. Please hurry and find a way to help me.", npc, creature) elseif player:getStorageValue(ThreatenedDreams.Mission01[1]) == 3 then npcHandler:say({ "You succeeded! It seems the poachers have read your little faked story about killing white deer and the ensuing doom. They stopped chasing me. Thank you! ...", @@ -80,13 +76,13 @@ local function creatureSayCallback(npc, creature, type, message) "There are fire, ice, energy and earth shrines. If you don't know their locations you can also reach them by most temples in this world. The elemental shrines will transport you to Feyrist now that you bear the magical seal.", }, npc, creature) player:setStorageValue(ThreatenedDreams.Mission01[1], 16) - else - npcHandler:say({ - "I indeed have some troubles since I'm travelling this part of the world. When I took over the body of a white deer I wasn't aware that such an animal is a sought after quarry for hunters and poachers. ...", - "Now I'm living in the constant danger of being caught and killed. Of course, I could just take over another animal but this deer has really grown on me. I'd like to help this beautiful stag but I need your assistance. Are you willing to help me?", - }, npc, creature) - npcHandler:setTopic(playerId, 1) end + elseif MsgContains(message, "help") and player:getStorageValue(ThreatenedDreams.Mission01[1]) < 1 then + npcHandler:say({ + "I indeed have some troubles since I'm travelling this part of the world. When I took over the body of a white deer I wasn't aware that such an animal is a sought after quarry for hunters and poachers. ...", + "Now I'm living in the constant danger of being caught and killed. Of course, I could just take over another animal but this deer has really grown on me. I'd like to help this beautiful stag but I need your assistance. Are you willing to help me?", + }, npc, creature) + npcHandler:setTopic(playerId, 1) elseif MsgContains(message, "yes") then if npcHandler:getTopic(playerId) == 1 then if player:getStorageValue(ThreatenedDreams.QuestLine) == 1 then @@ -131,7 +127,7 @@ keywordHandler:addKeyword({ "fae" }, StdModule.say, { }, }) -npcHandler:setMessage(MESSAGE_GREET, "Nature's blessing, traveller! |PLAYERNAME|!") +npcHandler:setMessage(MESSAGE_GREET, "Nature's blessing, traveller! May you not be affected by any sinister force.") npcHandler:setMessage(MESSAGE_FAREWELL, "May your path always be even.") npcHandler:setMessage(MESSAGE_WALKAWAY, "May your path always be even.") diff --git a/data-otservbr-global/npc/angelo.lua b/data-otservbr-global/npc/angelo.lua index ca73a5a6544..e770704a75a 100644 --- a/data-otservbr-global/npc/angelo.lua +++ b/data-otservbr-global/npc/angelo.lua @@ -52,18 +52,18 @@ end local function greetCallback(npc, creature) local playerId = creature:getId() - local player = Player(creature) - -- Se estiver na 1º missão - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 1 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 1 then npcHandler:setMessage(MESSAGE_GREET, "The Druid of Crunor? He told you that a new cave appeared here? That's right. I'm the head of a {project} that tries to find out more about this new {area}.") - elseif player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 9 then + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 9 then npcHandler:setMessage(MESSAGE_GREET, "Just get out of my way! You killed this beautiful creature. I have nothing more to say. Damn druid of Crunor!") - -- Se já tiver após a 1º missão - elseif player:getStorageValue(Storage.CultsOfTibia.Life.Mission) > 1 then + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) > 1 then npcHandler:setMessage(MESSAGE_GREET, "How is your {mission} going?") + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) < 1 then + npcHandler:setMessage(MESSAGE_GREET, "The Druid of Crunor? He told you that a new cave appeared here? That's right. I'm the head of a project that tries to find out more about this new area.") end + return true end local function creatureSayCallback(npc, creature, type, message) @@ -74,88 +74,79 @@ local function creatureSayCallback(npc, creature, type, message) return false end - -- Sequência para pegar a quest - if MsgContains(message, "project") then - npcHandler:say({ "The project is called 'Sandy {Cave} Project' and is funded by the {MoTA}. Its goal is the investigation of this {cave}." }, npc, creature) - npcHandler:setTopic(playerId, 2) - elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "mota") then - npcHandler:say({ "MoTA is short for the recently founded Museum of Tibian Arts. We work together in close collaboration. New {results} are communicated to the museum instantly." }, npc, creature) - npcHandler:setTopic(playerId, 3) - elseif npcHandler:getTopic(playerId) == 3 and MsgContains(message, "results") then - npcHandler:say({ "We have no scientific results so far to reach our {goal}, because my workers aren't back yet. Should I be {worried}?" }, npc, creature) - npcHandler:setTopic(playerId, 4) - elseif npcHandler:getTopic(playerId) == 4 and MsgContains(message, "yes") then - npcHandler:say({ "Alright. I have to find out why they don't return. But I'm old and my back aches. Would you like to go there and look for my workers?" }, npc, creature) - npcHandler:setTopic(playerId, 5) - elseif npcHandler:getTopic(playerId) == 5 and MsgContains(message, "yes") then - npcHandler:say({ "Fantastic! Go there and then tell me what you've seen. I've oppened the door for you. Take care of yourself!" }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 2) - player:setStorageValue(Storage.CultsOfTibia.Life.AccessDoor, 1) - npcHandler:setTopic(playerId, 0) - - -- Inútil - elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "cave") then - npcHandler:say({ "We don't know exactly why this cave has now exposed an entry via the {dark pyramid}. It seems that the cave already existed for a long time, however, without a connection to our world. Maybe some smaller earth movements have changed the situation." }, npc, creature) - npcHandler:setTopic(playerId, 11) - elseif npcHandler:getTopic(playerId) == 11 and MsgContains(message, "dark pyramid") then - npcHandler:say({ "We don't know yet to wich extent the cave and the dark pyramid belong together. Thisi s what we try to find out. Maybe the history of this place has to be rewritten." }, npc, creature) - npcHandler:setTopic(playerId, 0) - end - - -- Depois de encontrar o Oasis - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 3 then if MsgContains(message, "mission") then - npcHandler:say({ "The scientists are still missing? You just found some strange green shining mummies and a big oasis? I give you this analysis tool for the water of the oasis. Maybe that's the key. Could you bring me a sample of this water?" }, npc, creature) + npcHandler:say("The scientists are still missing? You just found some strange green shining mummies and a big oasis? I give you this analysis tool for the water of the oasis. Maybe that's the key. Could you bring me a sample of this water?", npc, creature) npcHandler:setTopic(playerId, 15) elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 15 then - npcHandler:say({ "Very good. Hopefully analysing this sample will get us closer to the solution of this mistery." }, npc, creature) + npcHandler:say("Very good. Hopefully analysing this sample will get us closer to the solution of this mistery.", npc, creature) player:addItem(25305, 1) - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 4) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 4) end end - -- Depois de usar o analyzing tool - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 5 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 5 then if MsgContains(message, "mission") then - npcHandler:say({ "Do you have the sample I asked you for?" }, npc, creature) + npcHandler:say("Do you have the sample I asked you for?", npc, creature) npcHandler:setTopic(playerId, 16) elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 16 then - npcHandler:say({ "Thanks a lot. Let me check the result. Well, I think you need the counteragent. Please apply it to the oasis!" }, npc, creature) + npcHandler:say("Thanks a lot. Let me check the result. Well, I think you need the counteragent. Please apply it to the oasis!", npc, creature) player:addItem(25304, 1) - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 6) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 6) end end - -- Depois de usar o conteragent - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 7 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 7 then if MsgContains(message, "mission") then - npcHandler:say({ "What has happened? You applied the counteragent to the oasis and then it was destroyed by a sandstorm? Keep on investigating the place." }, npc, creature) + npcHandler:say("What has happened? You applied the counteragent to the oasis and then it was destroyed by a sandstorm? Keep on investigating the place.", npc, creature) npcHandler:setTopic(playerId, 17) end end - -- after killing the boss the sandking - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 8 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 8 then npcHandler:say("Just get out of my way! You killed this beautiful creature. I have nothing more to say. Damn druid of Crunor!", npc, creature) - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 9) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 9) end - ----------------------------------------- MOTA ------------------------------- - -- Pedindo o Magnifier de Gareth - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 6 then + + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 6 then if MsgContains(message, "magnifier") then - npcHandler:say({ "{Gareth} told you that there are rumours about fake artefacts in the MoTA? And it is your task to check that with a magnifier? I see. I don't need one right now, so you can have one of mine. You find one in the crate over there." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 7) + npcHandler:say("{Gareth} told you that there are rumours about fake artefacts in the MoTA? And it is your task to check that with a magnifier? I see. I don't need one right now, so you can have one of mine. You find one in the crate over there.", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 7) end end - -- Pedindo a pintura de Gareth para Angelo - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 10 then - if MsgContains(message, "picture") then - npcHandler:say({ "So you found out that one artefact in the MoTA is fake? And {Gareth} sent you to me to get a new artefact as a replacement? Sorry, I hardly know you so I don't trust you. I won't help you with that!" }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 11) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 10 then + if MsgContains(message, "artefact") then + npcHandler:say("So you found out that one artefact in the MoTA is fake? And {Gareth} sent you to me to get a new artefact as a replacement? Sorry, I hardly know you so I don't trust you. I won't help you with that!", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 11) end end + if MsgContains(message, "project") then + npcHandler:say("The project is called 'Sandy {Cave} Project' and is funded by the {MoTA}. Its goal is the investigation of this {cave}.", npc, creature) + npcHandler:setTopic(playerId, 2) + elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "mota") then + npcHandler:say("MoTA is short for the recently founded Museum of Tibian Arts. We work together in close collaboration. New {results} are communicated to the museum instantly.", npc, creature) + npcHandler:setTopic(playerId, 3) + elseif npcHandler:getTopic(playerId) == 3 and MsgContains(message, "results") then + npcHandler:say("We have no scientific results so far to reach our {goal}, because my workers aren't back yet. Should I be {worried}?", npc, creature) + npcHandler:setTopic(playerId, 4) + elseif npcHandler:getTopic(playerId) == 4 and MsgContains(message, "worried") then + npcHandler:say("Then I have to find out why they don't return. But I'm old and my back aches. Would you like to go there and look for my workers?", npc, creature) + npcHandler:setTopic(playerId, 5) + elseif npcHandler:getTopic(playerId) == 5 and MsgContains(message, "yes") then + npcHandler:say("Fantastic! Go there and then tell me what you've seen. I've opened the door for you. Take care of yourself!", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.AccessDoor, 1) + npcHandler:setTopic(playerId, 0) + elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "cave") then + npcHandler:say("We don't know exactly why this cave has now exposed an entry via the {dark pyramid}. It seems that the cave already existed for a long time, however, without a connection to our world. Maybe some smaller earth movements have changed the situation.", npc, creature) + npcHandler:setTopic(playerId, 11) + elseif npcHandler:getTopic(playerId) == 11 and MsgContains(message, "dark pyramid") then + npcHandler:say("We don't know yet to wich extent the cave and the dark pyramid belong together. Thisi s what we try to find out. Maybe the history of this place has to be rewritten.", npc, creature) + npcHandler:setTopic(playerId, 0) + end + return true end diff --git a/data-otservbr-global/npc/buddel_helheim.lua b/data-otservbr-global/npc/buddel_helheim.lua index 88f94ccfa27..c1b526270f5 100644 --- a/data-otservbr-global/npc/buddel_helheim.lua +++ b/data-otservbr-global/npc/buddel_helheim.lua @@ -79,7 +79,7 @@ addTravelKeyword("svargrond", "You know a town nicer than this? NICER DICER! Apr end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -90,7 +90,7 @@ addTravelKeyword("okolnir", "It's nice there. Except of the ice dragons which ar end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -101,7 +101,7 @@ addTravelKeyword("tyrsung", "*HICKS* Big, big island east of here. Venorian hunt end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -112,7 +112,7 @@ addTravelKeyword("camp", "Both of you look like you could defend yourself! If yo end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) diff --git a/data-otservbr-global/npc/buddel_okolnir.lua b/data-otservbr-global/npc/buddel_okolnir.lua index f21ff049f4b..e4c9ea84f4a 100644 --- a/data-otservbr-global/npc/buddel_okolnir.lua +++ b/data-otservbr-global/npc/buddel_okolnir.lua @@ -82,7 +82,7 @@ addTravelKeyword("svargrond", "You know a town nicer than this? NICER DICER! Apr end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -93,7 +93,7 @@ addTravelKeyword("camp", "Both of you look like you could defend yourself! If yo end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -104,7 +104,7 @@ addTravelKeyword("helheim", "T'at is a small island to the east.", Position(3246 end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -117,7 +117,7 @@ addTravelKeyword("tyrsung", "*HICKS* Big, big island east of here. Venorian hunt end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) diff --git a/data-otservbr-global/npc/buddel_raider_camp.lua b/data-otservbr-global/npc/buddel_raider_camp.lua index 06b69175967..11cc062a2b6 100644 --- a/data-otservbr-global/npc/buddel_raider_camp.lua +++ b/data-otservbr-global/npc/buddel_raider_camp.lua @@ -82,7 +82,7 @@ addTravelKeyword("svargrond", "You know a town nicer than this? NICER DICER! Apr end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -93,7 +93,7 @@ addTravelKeyword("okolnir", "It's nice there. Except of the ice dragons which ar end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -104,7 +104,7 @@ addTravelKeyword("helheim", "T'at is a small island to the east.", Position(3246 end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -117,7 +117,7 @@ addTravelKeyword("tyrsung", "*HICKS* Big, big island east of here. Venorian hunt end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) diff --git a/data-otservbr-global/npc/buddel_tyrsung.lua b/data-otservbr-global/npc/buddel_tyrsung.lua index cb9025b1a91..65cbaf73066 100644 --- a/data-otservbr-global/npc/buddel_tyrsung.lua +++ b/data-otservbr-global/npc/buddel_tyrsung.lua @@ -82,7 +82,7 @@ addTravelKeyword("svargrond", "You know a town nicer than this? NICER DICER! Apr end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -93,7 +93,7 @@ addTravelKeyword("okolnir", "It's nice there. Except of the ice dragons which ar end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -104,7 +104,7 @@ addTravelKeyword("helheim", "T'at is a small island to the east.", Position(3246 end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) @@ -117,7 +117,7 @@ addTravelKeyword("camp", "Both of you look like you could defend yourself! If yo end, function() return math.random(5) > 1 end, function(player) - return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) < 8 + return player:getStorageValue(Storage.Quest.U8_0.BarbarianTest.Questline) == 8 end, function(player) return player:getItemCount(3097) > 0 end, function(player) diff --git a/data-otservbr-global/npc/charles.lua b/data-otservbr-global/npc/charles.lua index 9622620006a..3eb9fe2b82c 100644 --- a/data-otservbr-global/npc/charles.lua +++ b/data-otservbr-global/npc/charles.lua @@ -56,35 +56,81 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end --- Travel -local function addTravelKeyword(keyword, cost, destination, condition) - if condition then - keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = "I'm sorry but I don't sail there." }, condition) +local shortcuts = { + ["thais"] = { price = 100, position = Position(32310, 32210, 6) }, + ["edron"] = { price = 90, position = Position(33173, 31764, 6) }, + ["liberty bay"] = { price = 20, position = Position(32285, 32891, 6) }, + ["yalahar"] = { price = 200, position = Position(32816, 31272, 6) }, +} + +local isles = { + [1] = { isMission = true, position = Position(32031, 32463, 7) }, + [2] = { isMission = false, position = Position(33454, 32160, 7) }, + [3] = { isMission = false, position = Position(32112, 31745, 7) }, + [4] = { isMission = false, position = Position(32457, 32937, 7) }, +} + +local function creatureSayCallback(npc, creature, type, message) + local player = Player(creature) + local playerId = player:getId() + + if not npcHandler:checkInteraction(npc, creature) then + return false end - local travelKeyword = keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = "Do you seek a passage to " .. keyword:titleCase() .. " for |TRAVELCOST|?", cost = cost, discount = "postman" }) - travelKeyword:addChildKeyword({ "yes" }, StdModule.travel, { npcHandler = npcHandler, premium = false, cost = cost, discount = "postman", destination = destination }) - travelKeyword:addChildKeyword({ "no" }, StdModule.say, { npcHandler = npcHandler, text = "We would like to serve you some time.", reset = true }) + if MsgContains(message, "shortcut") and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline) >= 1 then + npcHandler:say({ + "This passage is shorter and costs less gold - but on the other hand it is also a bit riskier. On this route there are frequent tempests and the severe winds may blow a passenger over board. ...", + "Few ship captains would sail this route. But if you want to take the risk, I can bring you to Thais, Edron, Liberty Bay or Yalahar for less gold than usual. Interested?", + }, npc, creature) + npcHandler:setTopic(playerId, 5) + elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 5 then + npcHandler:say("Do you seek a shortcut passage to {Thais} for 100 gold, to {Edron} for 90 gold, to {Liberty Bay} for 20 gold or to {Yalahar} for 200 gold?", npc, creature) + npcHandler:setTopic(playerId, 6) + elseif npcHandler:getTopic(playerId) == 6 then + local travelTo = shortcuts[message:lower()] + if travelTo then + if player:removeMoney(travelTo.price) then + local r = math.random(1, #isles) + local chance = math.random(1, 10) + if chance <= 3 then + player:teleportTo(travelTo.position) + else + player:teleportTo(isles[r].position) + if isles[r].isMission and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline) < 2 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, 2) + end + end + npcHandler:say("Set the sails and good luck to us!", npc, creature) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + return true + else + npcHandler:say("You don't have enough money.", npc, creature) + end + end + else + local function addTravelKeyword(keyword, cost, destination, condition) + if condition then + keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = "I'm sorry but I don't sail there." }, condition) + end + local travelKeyword = keywordHandler:addKeyword({ keyword }, StdModule.say, { npcHandler = npcHandler, text = "Do you seek a passage to " .. keyword:titleCase() .. " for |TRAVELCOST|?", cost = cost, discount = "postman" }) + travelKeyword:addChildKeyword({ "yes" }, StdModule.travel, { npcHandler = npcHandler, premium = false, cost = cost, discount = "postman", destination = destination }) + travelKeyword:addChildKeyword({ "no" }, StdModule.say, { npcHandler = npcHandler, text = "We would like to serve you some time.", reset = true }) + end + addTravelKeyword("edron", 150, Position(33173, 31764, 6)) + addTravelKeyword("venore", 160, Position(32954, 32022, 6)) + addTravelKeyword("yalahar", 260, Position(32816, 31272, 6), function(player) + return player:getStorageValue(Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.PortHope) ~= 1 and player:getStorageValue(Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.TownsCounter) < 5 + end) + addTravelKeyword("ankrahmun", 110, Position(33092, 32883, 6)) + addTravelKeyword("darashia", 180, Position(33289, 32480, 6)) + addTravelKeyword("thais", 160, Position(32310, 32210, 6)) + addTravelKeyword("liberty bay", 50, Position(32285, 32892, 6)) + addTravelKeyword("carlin", 120, Position(32387, 31820, 6)) + end end -addTravelKeyword("edron", 150, Position(33173, 31764, 6)) -addTravelKeyword("venore", 160, Position(32954, 32022, 6)) -addTravelKeyword("yalahar", 260, Position(32816, 31272, 6), function(player) - return player:getStorageValue(Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.PortHope) ~= 1 and player:getStorageValue(Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.TownsCounter) < 5 -end) -addTravelKeyword("ankrahmun", 110, Position(33092, 32883, 6)) -addTravelKeyword("darashia", 180, Position(33289, 32480, 6)) -addTravelKeyword("thais", 160, Position(32310, 32210, 6)) -addTravelKeyword("liberty bay", 50, Position(32285, 32892, 6)) -addTravelKeyword("carlin", 120, Position(32387, 31820, 6)) -addTravelKeyword("shortcut", 100, Position(32029, 32466, 7), function(player) - return player:getStorageValue(Storage.TheSecretLibrary.PinkTel) == 2 and player:getStorageValue(Storage.TheSecretLibrary.Mota) == 12 -end) - --- Kick keywordHandler:addKeyword({ "kick" }, StdModule.kick, { npcHandler = npcHandler, destination = { Position(32535, 32792, 6), Position(32536, 32778, 6) } }) - --- Basic keywordHandler:addKeyword({ "sail" }, StdModule.say, { npcHandler = npcHandler, text = "Where do you want to go - {Thais}, {Darashia}, {Venore}, {Liberty Bay}, {Ankrahmun}, {Yalahar} or {Edron?}" }) keywordHandler:addKeyword({ "passage" }, StdModule.say, { npcHandler = npcHandler, text = "Where do you want to go - {Thais}, {Darashia}, {Venore}, {Liberty Bay}, {Ankrahmun}, {Yalahar} or {Edron?}" }) keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "Im the captain of the Poodle, the proudest ship on all oceans." }) @@ -96,6 +142,9 @@ keywordHandler:addKeyword({ "svargrond" }, StdModule.say, { npcHandler = npcHand npcHandler:setMessage(MESSAGE_GREET, "Ahoy. Where can I sail you today?") npcHandler:setMessage(MESSAGE_FAREWELL, "Bye.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Bye.") + +npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) -- npcType registering the npcConfig table diff --git a/data-otservbr-global/npc/dedoras.lua b/data-otservbr-global/npc/dedoras.lua index 79ac24a9678..1e77480a4b9 100644 --- a/data-otservbr-global/npc/dedoras.lua +++ b/data-otservbr-global/npc/dedoras.lua @@ -50,20 +50,35 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -local function greetCallback(npc, creature) - local player = Player(creature) - local playerId = player:getId() +local quests = { + [1] = { stg = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, value = 4 }, + [2] = { stg = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, value = 8 }, + [3] = { stg = Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, value = 7 }, + [4] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline, value = 3 }, + [5] = { stg = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 9 }, + [6] = { stg = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, value = 8 }, +} - if player:getStorageValue(Storage.Kilmaresh.First.Access) < 1 then - npcHandler:setMessage(MESSAGE_GREET, "How could I help you?") -- It needs to be revised, it's not the same as the global - npcHandler:setTopic(playerId, 1) - elseif (player:getStorageValue(Storage.Kilmaresh.First.JamesfrancisTask) >= 0 and player:getStorageValue(Storage.Kilmaresh.First.JamesfrancisTask) <= 50) and player:getStorageValue(Storage.Kilmaresh.First.Mission) < 3 then - npcHandler:setMessage(MESSAGE_GREET, "How could I help you?") -- It needs to be revised, it's not the same as the global - npcHandler:setTopic(playerId, 15) - elseif player:getStorageValue(Storage.Kilmaresh.First.Mission) == 4 then - npcHandler:setMessage(MESSAGE_GREET, "How could I help you?") -- It needs to be revised, it's not the same as the global - player:setStorageValue(Storage.Kilmaresh.First.Mission, 5) - npcHandler:setTopic(playerId, 20) +local function startMission(pid, storage, value) + local player = Player(pid) + if player then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Questlog) < 1 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Questlog, 1) + end + if player:getStorageValue(storage) < value then + player:setStorageValue(storage, value) + end + end +end + +local function isQuestDone(pid) + local player = Player(pid) + if player then + for i = 1, #quests do + if player:getStorageValue(quests[i].stg) ~= quests[i].value then + return false + end + end end return true end @@ -76,36 +91,227 @@ local function creatureSayCallback(npc, creature, type, message) return false end - if MsgContains(message, "report") and player:getStorageValue(Storage.TheSecretLibrary.PinkTel) == 1 then - npcHandler:say({ "Talk to Captain Charles in Port Hope. He told me that he once ran ashore on a small island where he discovered a small ruin. The architecture was like nothing he had seen before." }, npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.PinkTel, 2) - npcHandler:setTopic(playerId, 1) - npcHandler:setTopic(playerId, 1) + local currentStorage = player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission) + if currentStorage < 0 then + currentStorage = 0 end - if MsgContains(message, "check") and player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 5 then + if MsgContains(message, "search") then npcHandler:say({ - "Marvellous! With this information combined we have all that's needed! ...", - "So let me see. ...", - "Hmm, interesting. And we shouldn't forget about the chant! Yes, excellent! ...", - "So listen: To enter the veiled library, travel to the white raven monastery on the Isle of Kings and enter its main altar room. ...", - "There, use an ordinary scythe on the right of the two monuments, while concentrating on this glyph here and chant the words: Chamek Athra Thull Zathroth ...", - "Oh, and one other thing. For your efforts I want to reward you with one of my old outfits, back from my adventuring days. May it suit you well! ...", - "Hurry now my friend. Time is of essence!", + "I gathered some lore on my own, but I desperately need more information that you might provide me. ...", + "My leads are the {museum} in thais, something strange in the darashian {desert}, rumors about {fishmen}, an ancient {order}, the mysterious {asuri}, or a lost {isle}?", }, npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 6) - npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "museum") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 7 then + npcHandler:say({ + "This is ...", + "An astonishing find to say the least! I'm certain it will help the efforts of accessing the library a lot!", + }, npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 8) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) < 1 then + npcHandler:say("I have heard that it was recently planned to expand the Museum of Tibian Arts. In the course of these activities unexpected difficulties occurred.", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 1) + end + elseif MsgContains(message, "desert") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline) == 8 then + npcHandler:say("That's simply a scientific sensation. It will provide me with lots of much needed knowledge!", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, 9) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline) < 1 then + npcHandler:say("There are rumors of a mysterious statue in the desert next to Darashia. Nobody really knows the meaning of it.", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, 1) + end + elseif MsgContains(message, "fishmen") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) == 7 then + npcHandler:say("You brought incredible news. This book proves an invaluable clue!", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, 8) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) < 1 then + npcHandler:say({ + "Sightings of strange fishmen in Tiquanda are stirring up the region. You should be careful when investigating this. ...", + "As far as I know a scholar in Edron already dealt with fish-like creatures before.", + }, npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, 1) + end + elseif MsgContains(message, "order") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline) == 2 then + npcHandler:say("You brought incredible news. This book proves an invaluable clue!", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline, 3) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline) < 1 then + npcHandler:say({ + "Our world has seen many noble knights and orders throughout the centuries. Most of them vanished a long time ago but only few under such mysterious circumstances as the Order of the Falcon. ...", + "This noble alliance of honourable knights once resided in Edron to serve the king. Legend has it they vanished practically over night. Rumor has it their disappearance is connected to a forbidden book.", + }, npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline, 1) + end + elseif MsgContains(message, "asuri") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) == 6 then + npcHandler:say("This is incredible! Thank you so much for digging out that hint!", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 7) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) < 1 then + npcHandler:say({ + "There's a beautiful but very dangerous palace in the Tiquandan jungle. The young women who live there are actually demons and they are luring unsuspecting mortals in there. ...", + "A lucky survivor told me about a portal at the very top of the palace that may lead to another asuri hideout.", + }, npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 1) + end + elseif MsgContains(message, "isle") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline) == 3 then + npcHandler:say("Thank you so much for your efforts to provide this valuable piece of the puzzle!", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, currentStorage + 1) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, 4) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline) < 1 then + npcHandler:say("Talk to Captain Charles in Port Hope. He told me that he once ran ashore on a small island where he discovered a small ruin. The architecture was like nothing he had seen before.", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, 1) + end + elseif MsgContains(message, "progress") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission) < 6 then + npcHandler:say({ + "About what of your mission s do you want to report? The {museum}, the darashian {desert}, the rumors about strange {fishmen}, the ancient {order}, the mysterious {asuri}, or the lost {isle}? ...", + "Or shall me {check} how much information we acquired?", + }, npc, creature) + end + elseif MsgContains(message, "check") then + if isQuestDone(player:getId()) and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission) == 6 then + npcHandler:say({ + "Marvellous! With this information combined we have all that's needed! ...", + "So let me see. ...", + "Hmm, interesting. And we shouldn't forget about the chant! Yes, excellent! ...", + "So listen: To enter the veiled library, travel to the white raven monastery on the Isle of Kings and enter its main altar room. ...", + "There, use an ordinary scythe on the right of the two monuments, while concentrating on this glyph here and chant the words: Chamek Athra Thull Zathroth ...", + "Oh, and one other thing. For your efforts I want to reward you with one of my old outfits, back from my adventuring days. May it suit you well! ...", + "Hurry now my friend. Time is of essence!", + }, npc, creature) + player:addOutfit(1069, 0) + player:addOutfit(1070, 0) + player:addAchievement("Battle Mage") + startMission(player:getId(), Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission, 7) + npcHandler:setTopic(playerId, 0) + else + npcHandler:say("You're still searching for informations.", npc, creature) + end + end + + if MsgContains(message, "addon") and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission) == 7 then + npcHandler:say("Are you interested in one or two addons to your battle mage outfit?", npc, creature) npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "book") and npcHandler:getTopic(playerId) == 3 then + if player:getStorageValue(Storage.Quest.U11_80.BattleMageOutfits.Addon1) < 1 and player:getItemCount(28792) > 5 then + player:removeItem(28792, 5) + player:addOutfit(1069, 1) + player:addOutfit(1070, 1) + npcHandler:say("Very good! You gained the first addon to the battle mage outfit.", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.BattleMageOutfits.Addon1, 1) + npcHandler:setTopic(playerId, 0) + elseif player:getStorageValue(Storage.Quest.U11_80.BattleMageOutfits.Addon2) < 1 and player:getItemCount(28793) > 20 then + player:removeItem(28793, 20) + player:addOutfit(1069, 2) + player:addOutfit(1070, 2) + npcHandler:say("Very good! You gained the second addon to the battle mage outfit.", npc, creature) + startMission(player:getId(), Storage.Quest.U11_80.BattleMageOutfits.Addon2, 1) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "yes") then + if npcHandler:getTopic(playerId) == 1 then + npcHandler:say("I provide two addons. For the first one I need you to bring me five sturdy books. For the second addon you need twenty epaulettes. Do you want one of these addons?", npc, creature) + npcHandler:setTopic(playerId, 2) + elseif npcHandler:getTopic(playerId) == 2 then + npcHandler:say("What do you have for me: the sturdy books or the epaulettes?", npc, creature) + npcHandler:setTopic(playerId, 3) + end end return true end +keywordHandler:addKeyword({ "looking" }, StdModule.say, { npcHandler = npcHandler, text = "I need the help of some competent {adventurers} to handle a threat to all creation." }) +keywordHandler:addKeyword({ "value" }, StdModule.say, { npcHandler = npcHandler, text = "This leaves us with no choice but to take action into our own {hands}." }) +keywordHandler:addKeyword({ "threat" }, StdModule.say, { npcHandler = npcHandler, text = "I guess you know about the {background} and there is no need to tell you that the forces from beyond managed to acquire the parts of the godbreaker in a coup." }) +keywordHandler:addKeyword({ "disassembled" }, StdModule.say, { npcHandler = npcHandler, text = "The secret locations of the godbreaker {parts} were revealed and due to trickery, the minions of Variphor aquired all of them." }) +keywordHandler:addKeyword({ "obscure" }, StdModule.say, { npcHandler = npcHandler, text = "Those pieces of knowledge come in several forms and shapes. For most I can give you more or less specific hints where to start your {search}." }) +keywordHandler:addKeyword({ "hands" }, StdModule.say, { npcHandler = npcHandler, text = "You have to {find} the veiled hoard of Zathroth, breach it and destroy the knowledge how to use the godbreaker." }) +keywordHandler:addKeyword( + { "adventurer" }, + StdModule.say, + { npcHandler = npcHandler, text = { + "Of course the first to ask would be the famous Avar Tar, but I heard he's already on a quest of his own and ...", + "Well, let's say our last collaboration did not end too well. In fact, I'd be not even surprised if he pretended to not even know me. ...", + "So I have to look elsewhere to handle this new {threat}.", + } } +) +keywordHandler:addKeyword({ "background" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "The goodbreaker was created in ancient times, when the war between the gods and their minions was on its height. Its creation took aeons and incredible sacrifices. ...", + "Each part had to be crafted perfectly, to emulate the gods, so it would share 'the same place' with them. ...", + "Mere mortals can not even perceive it in his whole but only recognize the part of it that is the physical representation in our world. ...", + "If it was meant to be used as an actual weapon, as the ultimate threat, or if Zathroth was just tempted to use his knowledge in the ultimate way - to create something that could undo himself - we don't know. ...", + "However in the end even Zathroth deemed it too much of a threat but instead of destroying the contraption once and for all, it was {disassembled} and hidden away.", + }, +}) +keywordHandler:addKeyword( + { "parts" }, + StdModule.say, + { npcHandler = npcHandler, text = { + "The parts alone do them no good. To assemble the parts, great skill, immense power and forbidden knowledge are necessary. ...", + "The skill will be supplied by the fallen Yalahari and the power by Variphor itself. ...", + "The only thing they are still lacking is the knowledge to assemble and operate the {godbreaker}.", + } } +) +keywordHandler:addKeyword({ "godbreaker" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "The godbreaker is a complex artifact. Incantation woven into incantation. The powers bound into it are so immense that the slightest mishandling could prove disastrous. ...", + "o figure out how it works, let alone how it can be operated safely, could require several centuries of tireless study. And even then this information would be only partial. ...", + "Yet the creation and operation of the godbreaker is just the kind of forbidden {knowledge} Zathroth values most, so it was compiled and stored.", + }, +}) +keywordHandler:addKeyword({ "knowledge" }, StdModule.say, { npcHandler = npcHandler, text = { + "Of course the dangers of such knowledge were obvious. It was hidden in a sacred place devoted to Zathroth and dangerous knowledge. ...", + "The hidden library, the forbidden hoard, the shrouded trove of knowledge or the veiled hoard of forbidden knowledge, the place has many names in many {myths}.", +} }) +keywordHandler:addKeyword({ "myths" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "The myths agree that the place is well hidden, extremely guarded and contains some of the most powerful pieces of knowledge in this world and probably beyond. ...", + "However the knowledge about the godbreaker now poses a threat to all existence. In the hands of Variphor it can cause disaster in previously unknown ways. The gods themselves are in {peril}.", + }, +}) +keywordHandler:addKeyword({ "peril" }, StdModule.say, { npcHandler = npcHandler, text = { + "Regardless of the dangers, the cult of Zathroth refused to destroy the knowledge of the godbreaker for good. ...", + "They {value} dangerous knowledge that much, that they are unable to part from it, even when faced with the utter destruction of creation.", +} }) +keywordHandler:addKeyword( + { "find" }, + StdModule.say, + { npcHandler = npcHandler, text = { + "I know it's asked much but it's no longer a matter of choice. ...", + "The enemy is moving and I have reports that suggest the minions of Variphor are actively searching for Zathroth's library. They must not be allowed to succeed. ...", + "We must be the first to {reach} the hoard and make sure the enemy doesn't get the information he needs.", + } } +) +keywordHandler:addKeyword({ "reach" }, StdModule.say, { npcHandler = npcHandler, text = { + "I'd recommend to follow the few leads me and my associates could gather so far. ...", + "Old myths, some {rumors} about old texts and other pieces of knowledge that I could use to figure out where to locate the hidden library and how to enter it.", +} }) +keywordHandler:addKeyword({ "rumors" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "Hints about the shrouded hoard are numerous, though most are general mentions in texts that deal with Zathroth. But there are other sources. ...", + "Like texts about ancient liturgies of Zathroth and historical documents that might give us clues. I already compiled everything of value from the sources that were openly available. ...", + "To gather the more {obscure} parts of knowledge, however, I'll need your help.", + }, +}) + +npcHandler:setMessage(MESSAGE_GREET, "Greetings seekers of knowledge. You seem to be just the person I'm {looking} for.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") -npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) -npcHandler:setCallback(CALLBACK_REMOVE_INTERACTION, onReleaseFocus) + npcHandler:setCallback(CALLBACK_GREET, greetCallback) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) -- npcType registering the npcConfig table diff --git a/data-otservbr-global/npc/denominator.lua b/data-otservbr-global/npc/denominator.lua index e41ed2c051c..ab1e1c79667 100644 --- a/data-otservbr-global/npc/denominator.lua +++ b/data-otservbr-global/npc/denominator.lua @@ -46,15 +46,15 @@ npcType.onCloseChannel = function(npc, creature) end local playerLastResp = {} + local function greetCallback(npc, creature) local playerId = creature:getId() local player = Player(creature) local playerId = player:getId() - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 13 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 13 then npcHandler:setMessage(MESSAGE_GREET, "Enter answers for the following {questions}:") - npcHandler:setTopic(playerId, 1) else npcHandler:setMessage(MESSAGE_GREET, "Greetings.") end @@ -63,31 +63,31 @@ end local quiz1 = { [1] = { - p = "The sum of first and second digit?", + p = "The sum of the first and second digit?", r = function(player) - player:setStorageValue(Storage.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.CultsOfTibia.MotA.Stone2)) - return player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2)) + return player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) end, }, [2] = { - p = "The sum of second and third digit?", + p = "The sum of the second and third digit?", r = function(player) - player:setStorageValue(Storage.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.CultsOfTibia.MotA.Stone2) + player:getStorageValue(Storage.CultsOfTibia.MotA.Stone3)) - return player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2) + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3)) + return player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) end, }, [3] = { - p = "The sum of first and third digit?", + p = "The sum of the first and third digit?", r = function(player) - player:setStorageValue(Storage.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.CultsOfTibia.MotA.Stone3)) - return player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3)) + return player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) end, }, [4] = { - p = "The digit sum?", + p = "The total digit sum?", r = function(player) - player:setStorageValue(Storage.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.CultsOfTibia.MotA.Stone2) + player:getStorageValue(Storage.CultsOfTibia.MotA.Stone3)) - return player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer, player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1) + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2) + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3)) + return player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) end, }, } @@ -96,7 +96,7 @@ local quiz2 = { [1] = { p = "Is the number prime?", r = function(player) - local stg = player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + local stg = player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) if stg < 1 then return 0 end @@ -113,9 +113,9 @@ local quiz2 = { end, }, [2] = { - p = "Does the number belong to a prime twing?", + p = "Does the number belong to a twin prime?", r = function(player) - local stg = player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) + local stg = player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) if stg < 2 then return 0 end @@ -131,23 +131,23 @@ local quiz2 = { return (incr == 2 and 1 or 0) end, }, - -- [2] = {p = "", r = ""} } local quiz3 = { [1] = { p = "Is the number divisible by 3?", r = function(player) - return (player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) % 3 == 0 and 1 or 0) + return (player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) % 3 == 0 and 1 or 0) end, }, [2] = { p = "Is the number divisible by 2?", r = function(player) - return (player:getStorageValue(Storage.CultsOfTibia.MotA.Answer) % 2 == 0 and 1 or 0) + return (player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Answer) % 2 == 0 and 1 or 0) end, }, } + local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -156,26 +156,23 @@ local function creatureSayCallback(npc, creature, type, message) return false end - -- Começou a quest - if MsgContains(message, "questions") and npcHandler:getTopic(playerId) == 1 then + -- Quest started + if MsgContains(message, "questions") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 13 then npcHandler:say("Ready to {start}?", npc, creature) npcHandler:setTopic(playerId, 2) - npcHandler:setTopic(playerId, 2) elseif MsgContains(message, "start") and npcHandler:getTopic(playerId) == 2 then - local perguntaid = math.random(#quiz1) - player:setStorageValue(Storage.CultsOfTibia.MotA.QuestionId, perguntaid) - npcHandler:say(quiz1[perguntaid].p, npc, creature) - npcHandler:setTopic(playerId, 3) + local questionId = math.random(#quiz1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId, questionId) + npcHandler:say(quiz1[questionId].p, npc, creature) npcHandler:setTopic(playerId, 3) elseif npcHandler:getTopic(playerId) == 3 then npcHandler:say(string.format("Your answer is %s, do you want to continue?", message), npc, creature) playerLastResp[playerId] = tonumber(message) npcHandler:setTopic(playerId, 4) - npcHandler:setTopic(playerId, 4) elseif npcHandler:getTopic(playerId) == 4 then if MsgContains(message, "yes") then - local resposta = quiz1[player:getStorageValue(Storage.CultsOfTibia.MotA.QuestionId)].r - if playerLastResp[playerId] ~= (tonumber(resposta(player))) then + local answer = quiz1[player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId)].r + if playerLastResp[playerId] ~= (tonumber(answer(player))) then npcHandler:say("Wrong. SHUT DOWN.", npc, creature) npcHandler:resetNpc(creature) npcHandler:removeInteraction(npc, creature) @@ -183,7 +180,6 @@ local function creatureSayCallback(npc, creature, type, message) else npcHandler:say("Correct. {Next} question?", npc, creature) npcHandler:setTopic(playerId, 5) - npcHandler:setTopic(playerId, 5) end elseif MsgContains(message, "no") then npcHandler:say("SHUT DOWN.", npc, creature) @@ -192,23 +188,21 @@ local function creatureSayCallback(npc, creature, type, message) return false end elseif MsgContains(message, "next") and npcHandler:getTopic(playerId) == 5 then - local perguntaid = math.random(#quiz2) - player:setStorageValue(Storage.CultsOfTibia.MotA.QuestionId, perguntaid) - npcHandler:say(quiz2[perguntaid].p, npc, creature) - npcHandler:setTopic(playerId, 6) + local questionId = math.random(#quiz2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId, questionId) + npcHandler:say(quiz2[questionId].p, npc, creature) npcHandler:setTopic(playerId, 6) elseif npcHandler:getTopic(playerId) == 6 then - local resp = 0 + local response = 0 if MsgContains(message, "no") then - resp = 0 + response = 0 elseif MsgContains(message, "yes") then - resp = 1 + response = 1 end - local resposta = quiz2[player:getStorageValue(Storage.CultsOfTibia.MotA.QuestionId)].r - if resp == resposta(player) then + local answer = quiz2[player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId)].r + if response == answer(player) then npcHandler:say("Correct. {Next} question?", npc, creature) npcHandler:setTopic(playerId, 7) - npcHandler:setTopic(playerId, 7) else npcHandler:say("Wrong. SHUT DOWN.", npc, creature) npcHandler:resetNpc(creature) @@ -216,23 +210,21 @@ local function creatureSayCallback(npc, creature, type, message) return false end elseif npcHandler:getTopic(playerId) == 7 and MsgContains(message, "next") then - local perguntaid = math.random(#quiz3) - player:setStorageValue(Storage.CultsOfTibia.MotA.QuestionId, perguntaid) - npcHandler:say(quiz3[perguntaid].p, npc, creature) - npcHandler:setTopic(playerId, 8) + local questionId = math.random(#quiz3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId, questionId) + npcHandler:say(quiz3[questionId].p, npc, creature) npcHandler:setTopic(playerId, 8) elseif npcHandler:getTopic(playerId) == 8 then - local resp = 0 + local response = 0 if MsgContains(message, "no") then - resp = 0 + response = 0 elseif MsgContains(message, "yes") then - resp = 1 + response = 1 end - local resposta = quiz3[player:getStorageValue(Storage.CultsOfTibia.MotA.QuestionId)].r - if resp == resposta(player) then + local answer = quiz3[player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId)].r + if response == answer(player) then npcHandler:say("Correct. {Last} question?", npc, creature) npcHandler:setTopic(playerId, 9) - npcHandler:setTopic(playerId, 9) else npcHandler:say("Wrong. SHUT DOWN.", npc, creature) npcHandler:resetNpc(creature) @@ -242,15 +234,13 @@ local function creatureSayCallback(npc, creature, type, message) elseif npcHandler:getTopic(playerId) == 9 and MsgContains(message, "last") then npcHandler:say("Tell me the correct number?", npc, creature) npcHandler:setTopic(playerId, 10) - npcHandler:setTopic(playerId, 10) elseif npcHandler:getTopic(playerId) == 10 then npcHandler:say(string.format("Your answer is %s, do you want to continue?", message), npc, creature) playerLastResp[playerId] = tonumber(message) npcHandler:setTopic(playerId, 11) - npcHandler:setTopic(playerId, 11) elseif npcHandler:getTopic(playerId) == 11 then if MsgContains(message, "yes") then - local correct = string.format("%d%d%d", player:getStorageValue(Storage.CultsOfTibia.MotA.Stone1), player:getStorageValue(Storage.CultsOfTibia.MotA.Stone2), player:getStorageValue(Storage.CultsOfTibia.MotA.Stone3)) + local correct = string.format("%d%d%d", player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1), player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2), player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3)) if tonumber(playerLastResp[playerId]) ~= (tonumber(correct)) then npcHandler:say("Wrong. SHUT DOWN.", npc, creature) npcHandler:resetNpc(creature) @@ -258,8 +248,8 @@ local function creatureSayCallback(npc, creature, type, message) return false else npcHandler:say("Correct. The lower door is now open. The druid of Crunor lies.", npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) + 1) - player:setStorageValue(Storage.CultsOfTibia.MotA.AccessDoorDenominator) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) + 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorDenominator) end elseif MsgContains(message, "no") then npcHandler:say("SHUT DOWN.", npc, creature) diff --git a/data-otservbr-global/npc/gail.lua b/data-otservbr-global/npc/gail.lua index 1c61a2cbc6d..e0b6062908b 100644 --- a/data-otservbr-global/npc/gail.lua +++ b/data-otservbr-global/npc/gail.lua @@ -76,10 +76,9 @@ local function creatureSayCallback(npc, creature, type, message) return false end - if MsgContains(message, "daughter") and player:getStorageValue(Storage.TheSecretLibrary.Peacock) == 1 then - npcHandler:say({ "I always feared that I lost her. And yet, all those years, I still had a gleam of hope. I'm devastated to learn about her fate - but at least I have certainty now. Thank you for telling me." }, npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.Peacock, 2) - npcHandler:setTopic(playerId, 1) + if MsgContains(message, "daughter") and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) == 3 then + npcHandler:say("I always feared that I lost her. And yet, all those years, I still had a gleam of hope. I'm devastated to learn about her fate - but at least I have certainty now. Thank you for telling me.", npc, creature) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 4) npcHandler:setTopic(playerId, 1) end diff --git a/data-otservbr-global/npc/gareth.lua b/data-otservbr-global/npc/gareth.lua index d50f86f11ae..5f783c04cba 100644 --- a/data-otservbr-global/npc/gareth.lua +++ b/data-otservbr-global/npc/gareth.lua @@ -55,14 +55,16 @@ local function greetCallback(npc, creature) local player = Player(creature) - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 1 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) < 1 or player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) > 14 then + npcHandler:setMessage(MESSAGE_GREET, "Welcome to the wonderful and only recently opened Museum of Tibian Arts! Free entrance for everybody, but patrons of the arts are wanted and favoured.") + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 1 then npcHandler:setMessage(MESSAGE_GREET, "The Druid of Crunor has sent you? He seems to know that this new museum shines like a diamond. Enjoy your stay! If you like to {support} this place, talk to me.") - elseif player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) > 1 and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) < 14 then + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) > 1 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) < 14 then npcHandler:setMessage(MESSAGE_GREET, "How is your {mission} going?") - elseif player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 14 then + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 14 then npcHandler:setMessage(MESSAGE_GREET, "You again? How could you flee from the last floor. The cultists should have 'dealt' with you! That beats me. You have to leave this place right now. There's nothing more to say.") - npcHandler:setTopic(playerId, 0) end + return true end @@ -74,64 +76,68 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local valor = 10000 + local value = 10000 - -- Começou a quest - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) < 2 then - if MsgContains(message, "support") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ "If you like to, you can pay some gold to become a patron of the arts for this wonderful museum. The price is 10,000 gold. Your personal gain will be priceless. Do you want to pay?" }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) < 2 then + if MsgContains(message, "patrons") then + npcHandler:say("If you like to, you can pay some gold to become a patron of the arts for this wonderful museum. The price is 10,000 gold. Your personal gain will be priceless. Do you want to {pay}?", npc, creature) npcHandler:setTopic(playerId, 2) - elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 2 then - if (player:getMoney() + player:getBankBalance()) >= valor then - npcHandler:say({ "This is a very wise decision. You won't regret it. Congratulations! As your first task I like you to investigate the crime scene of a theft wich occurred last night. ...", "A very varuable artefact has been stolen. I open the door for you. You can find the room on the same floor as we are right now." }, npc, creature) - npcHandler:setTopic(playerId, 3) - player:removeMoneyBank(valor) + elseif MsgContains(message, "pay") and npcHandler:getTopic(playerId) == 2 then + if (player:getMoney() + player:getBankBalance()) >= value then + npcHandler:say({ + "This is a very wise decision. You won't regret it. Congratulations! As your first task I like you to investigate the crime scene of a theft wich occurred last night. ...", + "A very varuable artefact has been stolen. I open the door for you. You can find the room on the same floor as we are right now.", + }, npc, creature) + player:removeMoneyBank(value) player:addItem(25689, 1) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 2) - player:setStorageValue(Storage.CultsOfTibia.MotA.AccessDoorInvestigation, 1) - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) - end + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorInvestigation, 1) + npcHandler:setTopic(playerId, 3) else - npcHandler:say({ "You don't have enough money." }, npc, creature) + npcHandler:say("You don't have enough money.", npc, creature) npcHandler:setTopic(playerId, 1) end end - - -- Reportando sobre o document - elseif MsgContains(message, "mission") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 3 then - npcHandler:say({ "They want us to buy the picture back. Unfortunately this artefact is so important that I don't see an alternative. Please got to Iwar in Kazordoon and pay the money." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 4) + elseif MsgContains(message, "mission") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 3 then + npcHandler:say("They want us to buy the picture back. Unfortunately this artefact is so important that I don't see an alternative. Please got to Iwar in Kazordoon and pay the money.", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 4) npcHandler:setTopic(playerId, 1) - - -- Depois de ter pago o Iwar - elseif MsgContains(message, "mission") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 5 then + elseif MsgContains(message, "mission") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 5 then npcHandler:say({ "Nice! I'm really happy to have the picture back. First of all I have to check if everything's fine. Then I'll put it back on its place. For now, I'd like you to find out if some rumours about fake pictures in the MOTA are true. ...", "Some say one of the small pictures in the entrance hall here is fake. For this reason you have to go to my friend {Angelo} and ask him to get a {magnifier} for the investigation.", "Then do your job here in the museum and come back.", }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 6) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 6) npcHandler:setTopic(playerId, 1) - - -- Depois de ter visto a pintura falsa - elseif MsgContains(message, "mission") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 9 then - npcHandler:say({ "So the rumours are true. How could this happen? I'll keep the picture at its place until we've got a replacement. Please fo to {Angelo} and ask him if he has a new artefact for our museum." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 10) - elseif MsgContains(message, "mission") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 11 then - npcHandler:say({ "You're back, nice. Angelo's team hasn't found an artefact yet? I thought the progress would be faster. Anyway thanks for you efforts. ...", "I have no work for you right now. If you like to, you can have a look at the last floor. I open the door for you." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 12) - player:setStorageValue(Storage.CultsOfTibia.MotA.AccessDoorGareth, 1) - - --------------------------------------- FALHAS ---------------------------------------------------------- - -- Se ainda não tiver visto a pintura falsa - elseif MsgContains(message, "mission") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 8 then - npcHandler:say({ "You didn't investigate the pictures yet. Do your job and then come back." }, npc, creature) + elseif MsgContains(message, "mission") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 9 then + npcHandler:say("So the rumours are true. How could this happen? I'll keep the picture at its place until we've got a replacement. Please fo to {Angelo} and ask him if he has a new artefact for our museum.", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 10) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "mission") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 11 then + npcHandler:say({ + "You're back, nice. Angelo's team hasn't found an artefact yet? I thought the progress would be faster. Anyway thanks for you efforts. ...", + "I have no work for you right now. If you like to, you can have a look at the last floor. I open the door for you.", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 12) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorGareth, 1) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "mission") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 8 then + npcHandler:say("You didn't investigate the pictures yet. Do your job and then come back.", npc, creature) + npcHandler:setTopic(playerId, 0) end - if MsgContains(message, "extension") and player:getStorageValue(Storage.TheSecretLibrary.LiquidDeath) == 11 then - if player:getStorageValue(Storage.TheSecretLibrary.LiquidDeath) == 11 then - npcHandler:say({ "It is planned to extend the MOTA. But this will take time, because our workers have faced a little problem." }, npc, creature) + if MsgContains(message, "extension") then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 6 then + npcHandler:say({ + "You have found an inscription I would like to translate for you. The tibianus cipher was used: ...", + "Those who are accorded the honour to visit this exclusive place will smash their blindness and face the truth. ...", + "Astonishingly, Dedoras from Cormaya has recently asked me for these kinds of inscriptions. For sure he is able to bring light into the darkness. You should visit him. ", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 7) + npcHandler:setTopic(playerId, 0) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 1 then + npcHandler:say("It is planned to extend the MOTA. But this will take time, because our workers have faced a little {problem}.", npc, creature) npcHandler:setTopic(playerId, 11) end elseif MsgContains(message, "problem") and npcHandler:getTopic(playerId) == 11 then @@ -144,28 +150,19 @@ local function creatureSayCallback(npc, creature, type, message) end elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 12 then if npcHandler:getTopic(playerId) == 12 then - npcHandler:say({ "You are a true patron of the arts! I have opened the construction site for you. Start your work right now!" }, npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.Mota, 1) - player:setStorageValue(Storage.TheSecretLibrary.LiquidDeath, 12) - npcHandler:setTopic(playerId, 13) + npcHandler:say("You are a true patron of the arts! I have opened the construction site for you. Start your work right now!", npc, creature) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 2) + npcHandler:setTopic(playerId, 0) end end - if MsgContains(message, "bone") and player:getStorageValue(Storage.TheSecretLibrary.Mota) == 2 then - npcHandler:say({ "Hmm, interesting. Several years ago I have read some books dealing with strange locking mechanisms. I think what you have found here is a bone lever of category 3. ...", "Normally this is not used because it is not secure. The production failed and the lever can always be activated as follows: back, back, up, right, left. Just have a try, it should work." }, npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.Mota, 3) - npcHandler:setTopic(playerId, 14) - end - - if MsgContains(message, "extension") and player:getStorageValue(Storage.TheSecretLibrary.Mota) == 11 then - npcHandler:say( - { "You have found an inscription I would like to translate for you. The tibianus cipher was used: ...", "Those who are accorded the honour to visit this exclusive place will smash their blindness and face the truth. ...", "Astonishingly, Dedoras from Cormaya has recently asked me for these kinds of inscriptions. For sure he is able to bring light into the darkness. You should visit him. " }, - npc, - creature - ) - player:setStorageValue(Storage.TheSecretLibrary.Mota, 12) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 1) - npcHandler:setTopic(playerId, 15) + if MsgContains(message, "bone") and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 4 then + npcHandler:say({ + "Hmm, interesting. Several years ago I have read some books dealing with strange locking mechanisms. I think what you have found here is a bone lever of category 3. ...", + "Normally this is not used because it is not secure. The production failed and the lever can always be activated as follows: back, back, up, right, left. Just have a try, it should work.", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 5) + npcHandler:setTopic(playerId, 0) end return true diff --git a/data-otservbr-global/npc/gelidrazahs_thirst.lua b/data-otservbr-global/npc/gelidrazahs_thirst.lua index a051dfb791e..beff8d7c6b9 100644 --- a/data-otservbr-global/npc/gelidrazahs_thirst.lua +++ b/data-otservbr-global/npc/gelidrazahs_thirst.lua @@ -72,7 +72,7 @@ local function creatureSayCallback(npc, creature, type, message) elseif MsgContains(message, "Svir") and npcHandler:getTopic(playerId) == 4 then npcHandler:say("That is correct. You satisfactorily answered all questions. You may pass and enter Gelidrazah's lair.", npc, creature) npcHandler:setTopic(playerId, 0) - player:setStorageValue(Storage.FirstDragon.GelidrazahAccess, 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.GelidrazahAccess, 1) else npcHandler:say("I don't know what you are talking about.", npc, creature) end diff --git a/data-otservbr-global/npc/gerimor.lua b/data-otservbr-global/npc/gerimor.lua index 1c7d4c8443e..0e8b0c0988d 100644 --- a/data-otservbr-global/npc/gerimor.lua +++ b/data-otservbr-global/npc/gerimor.lua @@ -55,12 +55,9 @@ local function greetCallback(npc, creature) local playerId = player:getId() if player then - npcHandler:setMessage( - MESSAGE_GREET, - "Greeting, |PLAYERNAME|! I welcome you to this sacred {place}. \z - If you are interested in {missions} just ask." - ) + npcHandler:setMessage(MESSAGE_GREET, "Greeting, |PLAYERNAME|! I welcome you to this sacred {place}. If you are interested in {missions} just ask.") end + return true end @@ -73,10 +70,8 @@ keywordHandler:addKeyword({ "place" }, StdModule.say, { keywordHandler:addKeyword({ "me" }, StdModule.say, { npcHandler = npcHandler, text = { - "I'm a member of a circle of persons, that joined wisdom and resources for a common purpose. \z - Let's say, we have an eye on the greater picture in the matters of our world. ...", - "We are watching and evaluating what is happening in our world. \z - Trying to avert the worst and offering a helping hand where we deem it needed. ...", + "I'm a member of a circle of persons, that joined wisdom and resources for a common purpose. Let's say, we have an eye on the greater picture in the matters of our world. ...", + "We are watching and evaluating what is happening in our world. Trying to avert the worst and offering a helping hand where we deem it needed. ...", "We usually avoid to interfere directly in the affairs of the world and vain politics are not our concern at all.", }, }) @@ -89,36 +84,30 @@ keywordHandler:addKeyword({ "circle" }, StdModule.say, { keywordHandler:addKeyword({ "persons" }, StdModule.say, { npcHandler = npcHandler, text = { - "Well, while I focus more on the matters of life, some of my peers have different approaches \z - and emphasize other aspects of the world more in their observations. ...", + "Well, while I focus more on the matters of life, some of my peers have different approaches and emphasize other aspects of the world more in their observations. ...", "Regardless we share a common goal of balance and harmony.", }, }) keywordHandler:addKeyword({ "approaches" }, StdModule.say, { npcHandler = npcHandler, - text = "We might not be many but we are diverse. \z - Our rather informal order came together in the dawn of time, when the wars of the gods ravaged the world.", + text = "We might not be many but we are diverse. Our rather informal order came together in the dawn of time, when the wars of the gods ravaged the world.", }) keywordHandler:addKeyword({ "dawn" }, StdModule.say, { npcHandler = npcHandler, text = { "Even we know the individual that was somewhat of our funder, only as the wise man. ...", - "He was the first to bring bright and dedicated minds together, \z - to bring at least a little order and guidance into troubled and chaotic times. ...", - "The order predates mankind and never bothered to give itself a name. \z - Such assumptions of pretence and vanity have no place in our mindset.", + "He was the first to bring bright and dedicated minds together, to bring at least a little order and guidance into troubled and chaotic times. ...", + "The order predates mankind and never bothered to give itself a name. Such assumptions of pretence and vanity have no place in our mindset.", }, }) keywordHandler:addKeyword({ "guidance" }, StdModule.say, { npcHandler = npcHandler, text = { - "Most times we are silent watchers and keeper of knowledge that share what they have learned with each other. \z - We are more concerned about knowledge and wisdom and power means little to us. ...", - "To solve problems we usually try to convince the right people to do the right thing. \z - We usually even lack the means for a more direct interference.", + "Most times we are silent watchers and keeper of knowledge that share what they have learned with each other. We are more concerned about knowledge and wisdom and power means little to us. ...", + "To solve problems we usually try to convince the right people to do the right thing. We usually even lack the means for a more direct interference.", }, }) @@ -126,113 +115,84 @@ keywordHandler:addKeyword({ "direct" }, StdModule.say, { npcHandler = npcHandler, text = { "Sometimes it's necessary to do something about a situation that became threatening to the world itself. ...", - "It is gladly a rare occurrence and usually it is sufficient to somewhat offer a guiding hand to \z - avert a course that would lead to more dire consequences. Nonetheless sometimes we have to interfere.", + "It is gladly a rare occurrence and usually it is sufficient to somewhat offer a guiding hand to avert a course that would lead to more dire consequences. Nonetheless sometimes we have to interfere.", }, }) keywordHandler:addKeyword({ "interfere" }, StdModule.say, { npcHandler = npcHandler, - text = "Interference comes in different forms. \z - In this particular case there is sadly little time for subtlety and a more direct approach is necessary.", + text = "Interference comes in different forms. In this particular case there is sadly little time for subtlety and a more direct approach is necessary.", }) keywordHandler:addKeyword({ "feyrist" }, StdModule.say, { npcHandler = npcHandler, - text = "The fae granted me permission to enter their hidden realm. \z - As a druid I'm in close touch with nature so I could gain their trust. \z - The nature spirits are inhabiting this peninsula for ages.", + text = "The fae granted me permission to enter their hidden realm. As a druid I'm in close touch with nature so I could gain their trust. The nature spirits are inhabiting this peninsula for ages.", }) keywordHandler:addKeyword({ "fae" }, StdModule.say, { npcHandler = npcHandler, text = { - "The fae vary greatly in size and appearance. \z - There are different kinds of fae like fauns, pixies, pookas, swan maidens, nymphs and boogies. \z - Those mystical creatures are wielding power in magic and elementals. ...", - "Most of them are rather reclusive and live peaceful lives in their secret realm. \z - Sometimes they are called the 'children of dreams' or 'the dream born' \z - because the fae are born from the mortals' dreams.", + "The fae vary greatly in size and appearance. There are different kinds of fae like fauns, pixies, pookas, swan maidens, nymphs and boogies. Those mystical creatures are wielding power in magic and elementals. ...", + "Most of them are rather reclusive and live peaceful lives in their secret realm. Sometimes they are called the 'children of dreams' or 'the dream born' because the fae are born from the mortals' dreams.", }, }) keywordHandler:addKeyword({ "fauns" }, StdModule.say, { npcHandler = npcHandler, text = { - "Fauns are half-human, half-beast nature spirits inhabiting the woods and mountains of Feyrist. \z - They are a slightly roguish but cheerful folk, lovers of wine and dancing. ...", - "Fauns show a youthful and graceful aspect but they are also brave and fearless \z - when it comes to defend themselves. As Maelyrra told me, they emerge from mortals' \z - dreams about celebrations, music and dancing. ...", - "Lately, some fauns on Feyrist are tainted by the mysterious, sinister force that is \z - threatening Feyrist as well as the rest of Tibia.", + "Fauns are half-human, half-beast nature spirits inhabiting the woods and mountains of Feyrist. They are a slightly roguish but cheerful folk, lovers of wine and dancing. ...", + "Fauns show a youthful and graceful aspect but they are also brave and fearless when it comes to defend themselves. As Maelyrra told me, they emerge from mortals' dreams about celebrations, music and dancing. ...", + "Lately, some fauns on Feyrist are tainted by the mysterious, sinister force that is threatening Feyrist as well as the rest of Tibia.", }, }) keywordHandler:addKeyword({ "pixies" }, StdModule.say, { npcHandler = npcHandler, text = { - "Pixies are small nature spirits and mythical creatures inhabiting the forests and plains of Feyrist. \z - They are generally benign, but at times, they may also display mischievous traits. ...", - "Like most of the fae, pixies love dancing and are often gathering in larger groups \z - to dance on secluded glades. Pixies love flowers, butterflies, shimmering beetles, \z - gems and other colourful things. ...", - "They also love the taste of honey, sweetened oat and ripe grapes. \z - As Maelyrra told me, pixies emerge from mortals' dreams about friends and family.", + "Pixies are small nature spirits and mythical creatures inhabiting the forests and plains of Feyrist. They are generally benign, but at times, they may also display mischievous traits. ...", + "Like most of the fae, pixies love dancing and are often gathering in larger groups to dance on secluded glades. Pixies love flowers, butterflies, shimmering beetles, gems and other colourful things. ...", + "They also love the taste of honey, sweetened oat and ripe grapes. As Maelyrra told me, pixies emerge from mortals' dreams about friends and family.", }, }) keywordHandler:addKeyword({ "pookas" }, StdModule.say, { npcHandler = npcHandler, text = { - "Pookas are nature spirits in animal form, looking like big hares with a faintly glittering fur. \z - They are benign but mischievous, for sure with good reason regarded as the tricksters among the fae. ...", - "Pookas love to play pranks on others, snitching and hiding things or telling made-up stories. \z - They are capricious and fickle creatures. \z - Pookas emerge from mortals' dreams about gems, treasures and gold. ...", - "Lately, some pookas on Feyrist are tainted by a mysterious, sinister force that is \z - threatening Feyrist as well as the rest of Tibia.", + "Pookas are nature spirits in animal form, looking like big hares with a faintly glittering fur. They are benign but mischievous, for sure with good reason regarded as the tricksters among the fae. ...", + "Pookas love to play pranks on others, snitching and hiding things or telling made-up stories. They are capricious and fickle creatures. Pookas emerge from mortals' dreams about gems, treasures and gold. ...", + "Lately, some pookas on Feyrist are tainted by a mysterious, sinister force that is threatening Feyrist as well as the rest of Tibia.", }, }) keywordHandler:addKeyword({ "swan maidens" }, StdModule.say, { npcHandler = npcHandler, text = { - "Swan maidens are fae who can shapeshift from human form to swan form. \z - The magical item allowing this transformation is a swan feather cloak, a garment with swan feathers attached. ...", - "Here on Feyrist it is always hard to tell whether a swan swimming on a lake \z - is an ordinary animal or a swan maiden in her bird shape. ...", - "They protect the wilds of their secret realm from every intruder and live in small \z - flocks along secluded lakeshores. As Maelyrra told me, swan maidens emerge from mortals' dreams about flying.", + "Swan maidens are fae who can shapeshift from human form to swan form. The magical item allowing this transformation is a swan feather cloak, a garment with swan feathers attached. ...", + "Here on Feyrist it is always hard to tell whether a swan swimming on a lake is an ordinary animal or a swan maiden in her bird shape. ...", + "They protect the wilds of their secret realm from every intruder and live in small flocks along secluded lakeshores. As Maelyrra told me, swan maidens emerge from mortals' dreams about flying.", }, }) keywordHandler:addKeyword({ "nymphs" }, StdModule.say, { npcHandler = npcHandler, text = { - "Nymphs are female nature spirits and usually take the form of beautiful, \z - young maidens who love to dance and sing. They dwell in the hills and forests of Feyrist, \z - often near lakes and streams and they can't die of old age nor illness. ...", - "They have a special, strong bond to the plants and animals of their domain and are very \z - protective of Feyrist's flora and fauna. As Maelyrra told me, nymphs emerge from mortals' dreams about love.", + "Nymphs are female nature spirits and usually take the form of beautiful, young maidens who love to dance and sing. They dwell in the hills and forests of Feyrist, often near lakes and streams and they can't die of old age nor illness. ...", + "They have a special, strong bond to the plants and animals of their domain and are very protective of Feyrist's flora and fauna. As Maelyrra told me, nymphs emerge from mortals' dreams about love.", }, }) keywordHandler:addKeyword({ "boogies" }, StdModule.say, { npcHandler = npcHandler, text = { - "Boogies are a rather twisted kind of fae. Other than pixies, nymphs or fauns they favour \z - underground caves and tunnels over forests or lush meadows. ...", - "Only at night, they are roaming the surface, chasing other fae and visitors to Feyrist alike. \z - They were once clumsy yet peaceful fae, but they are now twisted and tainted by a mysterious, sinister force.", + "Boogies are a rather twisted kind of fae. Other than pixies, nymphs or fauns they favour underground caves and tunnels over forests or lush meadows. ...", + "Only at night, they are roaming the surface, chasing other fae and visitors to Feyrist alike. They were once clumsy yet peaceful fae, but they are now twisted and tainted by a mysterious, sinister force.", }, }) keywordHandler:addKeyword({ "maelyrra" }, StdModule.say, { npcHandler = npcHandler, text = { - "She's the queen of a fae court. You can find her on a glade in the deep forest. \z - It was queen Maelyrra who granted me permission to stay here in Feyrist. ...", + "She's the queen of a fae court. You can find her on a glade in the deep forest. It was queen Maelyrra who granted me permission to stay here in Feyrist. ...", "I promised to inform her about anything I find out about the abominable force that threatens this world.", }, }) @@ -240,65 +200,49 @@ keywordHandler:addKeyword({ "maelyrra" }, StdModule.say, { keywordHandler:addKeyword({ "fae court" }, StdModule.say, { npcHandler = npcHandler, text = { - "The fae vary greatly in size and appearance. \z - There are different kinds of fae like fauns, pixies, pookas, swan maidens, nymphs and boogies. \z - Those mystical creatures are wielding power in magic and elementals. ...", - "Most of them are rather reclusive and live peaceful lives in their secret realm. \z - Sometimes they are called the ,children of dreams' or ,the dream born' \z - because the fae are born from the mortals' dreams.", + "The fae vary greatly in size and appearance. There are different kinds of fae like fauns, pixies, pookas, swan maidens, nymphs and boogies. Those mystical creatures are wielding power in magic and elementals. ...", + "Most of them are rather reclusive and live peaceful lives in their secret realm. Sometimes they are called the ,children of dreams' or ,the dream born' because the fae are born from the mortals' dreams.", }, }) keywordHandler:addKeyword({ "cults" }, StdModule.say, { npcHandler = npcHandler, text = { - "It doesn't seem that the cults share a common theme or object of reverence but there has to \z - be some connection beyond being at the centre of culminations of disruptive power from beyond. ...", - "The connection is of second thought though. Connected or not, they further the death of our world. \z - That alone makes it imperative to dig those cults out and destroy their cores. ...", - "We won't be able to rout our each and any movement but if we manage to neutralize the worst, \z - we gain some time and deny the enemy much of its leverage on the future of our world.", + "It doesn't seem that the cults share a common theme or object of reverence but there has to be some connection beyond being at the centre of culminations of disruptive power from beyond. ...", + "The connection is of second thought though. Connected or not, they further the death of our world. That alone makes it imperative to dig those cults out and destroy their cores. ...", + "We won't be able to rout our each and any movement but if we manage to neutralize the worst, we gain some time and deny the enemy much of its leverage on the future of our world.", }, }) keywordHandler:addKeyword({ "worst" }, StdModule.say, { npcHandler = npcHandler, text = { - "We have located some of the worst culminations of otherworldly presence and our sources \z - returned information about them with different results of success. ...", - "Some information I can provide you will be rather sparse and much is left to speculation \z - but you should have at least some lead where to go and investigate.", + "We have located some of the worst culminations of otherworldly presence and our sources returned information about them with different results of success. ...", + "Some information I can provide you will be rather sparse and much is left to speculation but you should have at least some lead where to go and investigate.", }, }) keywordHandler:addKeyword({ "investigate" }, StdModule.say, { npcHandler = npcHandler, - text = "Those cults have to be stopped by any means possible. \z - These are desperate times and they demand desperate actions.", + text = "Those cults have to be stopped by any means possible. These are desperate times and they demand desperate actions.", }) keywordHandler:addKeyword({ "actions" }, StdModule.say, { npcHandler = npcHandler, - text = "Spare lives where you see it fit but the cults may not be allowed to exist and disrupt \z - the fabric of the world even more.", + text = "Spare lives where you see it fit but the cults may not be allowed to exist and disrupt the fabric of the world even more.", }) keywordHandler:addKeyword({ "fabric" }, StdModule.say, { npcHandler = npcHandler, - text = "The weakened fabric of our reality still repels the unnatural intruder. The cults provide the \z - thing a hold and supply it with more power, even if we couldn't figure out yet, how this works at all.", + text = "The weakened fabric of our reality still repels the unnatural intruder. The cults provide the thing a hold and supply it with more power, even if we couldn't figure out yet, how this works at all.", }) keywordHandler:addKeyword({ "works" }, StdModule.say, { npcHandler = npcHandler, text = { - "We haven't completely figured out what our enemy exactly is. \z - For one, this thing defies all laws of nature and comprehension, ...", - "that understanding it is either impossible or twist a mind in ways that are not meant to be. \z - Also the Yalahari who figured out way too much about the thing, became tainted and changed by this knowledge ...", - "And ultimately not only fell and became his, they also provided the thing with something of their own, \z - be it knowledge, understanding or even direction, purpose. ...", + "We haven't completely figured out what our enemy exactly is. For one, this thing defies all laws of nature and comprehension, ...", + "that understanding it is either impossible or twist a mind in ways that are not meant to be. Also the Yalahari who figured out way too much about the thing, became tainted and changed by this knowledge ...", + "And ultimately not only fell and became his, they also provided the thing with something of their own, be it knowledge, understanding or even direction, purpose. ...", "In some way their tainted knowledge brought the unthinkable into a resemblance of existence. ...", - "That is why we cant dabble too much in figuring this out and rather concentrate on our \z - fight to severe its ties to our world.", + "That is why we cant dabble too much in figuring this out and rather concentrate on our fight to severe its ties to our world.", }, }) @@ -311,95 +255,86 @@ local config = { missions = { ["minotaurs"] = { text = { - "This is an animal-like cult. Only minotaurs can be found there, \z - but no idea what there are expecting and what they are worshipping. ...", + "This is an animal-like cult. Only minotaurs can be found there, but no idea what there are expecting and what they are worshipping. ...", "Maybe they are a bit different to the creatures you already know. Would you like to dinf out more for me?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "You have found the source of power which strengthened the minotaurs. Thanks a lot! Here your reward.", }, - storage = Storage.CultsOfTibia.Minotaurs.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, value = 5, rewardExp = 25000, }, ["prosperity"] = { text = { - "The alleged incentive to follow this cult is infinite prosperity. \z - Therefore most of the worshippers are already very rich citizens of Tibia. ...", - "This cult is abandoned in the recently opened new museum in Thais. \z - This can be entered in the Thais exhibition. Would you like to have a look at this cult?", + "The alleged incentive to follow this cult is infinite prosperity. Therefore most of the worshippers are already very rich citizens of Tibia. ...", + "This cult is abandoned in the recently opened new museum in Thais. This can be entered in the Thais exhibition. Would you like to have a look at this cult?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "Thanks a lot. As I already supposed the museum is just a disguise. ...", + 'You found out the true meaning. As you have described their cult object the AM on the floor might stand for "Aurea Manus". Here is your reward for your effort.', }, - storage = Storage.CultsOfTibia.MotA.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, value = 14, rewardExp = 50000, }, ["barkless"] = { text = { - "However, recently they became more prominent as their leader seems to hava taken a turn for the worse. \z - Rumors of violent acts and disappearing people are linked to this cult. ...", + "However, recently they became more prominent as their leader seems to hava taken a turn for the worse. Rumors of violent acts and disappearing people are linked to this cult. ...", "Someone... Should look into that, don't you think?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "The Penitent, thats what they called him? If their spiritual leader and creator of this following changed so radically...", + "Something far more dangerous must have stood behind this.", }, - storage = Storage.CultsOfTibia.Barkless.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, value = 6, rewardExp = 50000, }, ["orcs"] = { text = { - "Several Edron orcs have taken to a dangerous idol it seems. \z - It may not be too late to stop them if you act quickly. \z - A powerful cult of orcs with a broad following could prove unsurmountable in the end. ...", + "Several Edron orcs have taken to a dangerous idol it seems. It may not be too late to stop them if you act quickly. A powerful cult of orcs with a broad following could prove unsurmountable in the end. ...", }, completeText = { - "Then you got it. Thank you. Here is your reward.", - "Are you prepared to investigate?", + "That was no god - yet you rid the world of a being which, without the help of one, would not even have been here in the first place. Nicely done.", }, - storage = Storage.CultsOfTibia.Orcs.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Orcs.Mission, value = 2, rewardExp = 25000, }, ["life"] = { text = { - "Its worshippers wish for eternal, life free of pain and sorrow. \z - The entrance to this cult can be found in the dark pyramid. Would you life to investigate it for me?", + "Its worshippers wish for eternal, life free of pain and sorrow. The entrance to this cult can be found in the dark pyramid. Would you life to investigate it for me?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "Thanks a lot. You have revealed the mystery of this cult and killed the sandking. ...", + "The signature AM you have seen, could stand for 'Aeterna Exsistentia' regarding the eternal life. As a reward I give this to you.", }, - storage = Storage.CultsOfTibia.Life.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Life.Mission, value = 9, rewardExp = 50000, }, ["misguided"] = { text = { - "There's a camp of outlaws to the east of Thais. \z - Rumour has it that people are going missing but it's not linked to the bandits. ...", - "Lights have been seen at night in the abandoned ruin in the vicinity of the camp, \z - somewhere to the south-west. Brave enough to check it out?", + "There's a camp of outlaws to the east of Thais. Rumour has it that people are going missing but it's not linked to the bandits. ...", + "Lights have been seen at night in the abandoned ruin in the vicinity of the camp, somewhere to the south-west. Brave enough to check it out?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "So the leader of these... Misguided was actually controlled and not the other way round? Whatever is behind all this, that's some first-rate irony right there.", }, - storage = Storage.CultsOfTibia.Misguided.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, value = 4, rewardExp = 50000, }, ["humans"] = { text = { - "It's a forbidden and abandoned place but... There is an ancient temple of Zathroth beneath Carlin. \z - Some say it's not that abandoned anymore. ...", - "Voices, flickering lights in the dead of night, and even a strange gate like sphere wich leads to \z - who knows where. I can't really request this from you but... Someone should take a look, or not?", + "It's a forbidden and abandoned place but... There is an ancient temple of Zathroth beneath Carlin. Some say it's not that abandoned anymore. ...", + "Voices, flickering lights in the dead of night, and even a strange gate like sphere wich leads to who knows where. I can't really request this from you but... Someone should take a look, or not?", }, completeText = { - "Then you got it. Thank you. Here is your reward.", + "Zathroth wasn't behind this after all. That's good... what's not good is that we have to deal with an unknown power now, let's hope for the best.", }, - storage = Storage.CultsOfTibia.Humans.Mission, + storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Mission, value = 2, rewardExp = 25000, }, @@ -419,75 +354,37 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "missions") then - -- Final boss check - if player:getStorageValue(Storage.CultsOfTibia.FinalBoss.Mission) > 2 then - npcHandler:say( - "You have already fulfilled your job to my full satisfaction. \z - The cults are investigated and the final boss is eliminated. \z - I have nothing more for you to do. Fare you well!", - npc, - creature - ) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission) > 2 then + npcHandler:say("You have already fulfilled your job to my full satisfaction. The cults are investigated and the final boss is eliminated. I have nothing more for you to do. Fare you well!", npc, creature) npcHandler:setTopic(playerId, 0) elseif - player:getStorageValue(Storage.CultsOfTibia.Minotaurs.Mission) == 6 - and player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 10 - and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 15 - and player:getStorageValue(Storage.CultsOfTibia.Barkless.Mission) == 7 - and player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) == 5 - and player:getStorageValue(Storage.CultsOfTibia.Orcs.Mission) == 3 - and player:getStorageValue(Storage.CultsOfTibia.Humans.Mission) == 3 - and player:getStorageValue(Storage.CultsOfTibia.FinalBoss.Mission) < 2 + player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission) == 6 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 10 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 15 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission) == 7 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) == 5 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.Mission) == 3 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.Mission) == 3 + and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission) < 2 then - npcHandler:say( - "It seems to me that you have done all the missions I gave you. \z - All the cults have been revealed and now you can kill their leader, the final boss, \z - to save the world from a possible catastrophe.", - npc, - creature - ) + npcHandler:say({ + "Your actions have weakened the worldly anchors of the enemy and unveiled the source they use to strengthen their cults. ...", + "Our circle has used this opportunity to breach their protective shroud and aim a teleporter to this source. I would like to ask you to use it, to travel to this source and destroy it. ...", + "But be warned, you will need a group twice as great compared to those with which you defeated the cults. Go now, with my blessings.", + }, npc, creature) npcHandler:setTopic(playerId, 0) - if player:getStorageValue(Storage.CultsOfTibia.FinalBoss.Mission) < 1 then - player:setStorageValue(Storage.CultsOfTibia.FinalBoss.Mission, 1) - player:setStorageValue(Storage.CultsOfTibia.FinalBoss.AccessDoor, 1) - end - elseif player:getStorageValue(Storage.CultsOfTibia.FinalBoss.Mission) == 2 then - npcHandler:say("You did it! You put an end to the cults, and as a return, here's your reward.", npc, creature) - npcHandler:setTopic(playerId, 9) - local item = "" - if player:getVocation():getBaseId() == VOCATION.BASE_ID.SORCERER then - player:addItem(26190) - item = "reflecting crown" - end - if player:getVocation():getBaseId() == VOCATION.BASE_ID.DRUID then - player:addItem(26187) - item = "leaf crown" - end - if player:getVocation():getBaseId() == VOCATION.BASE_ID.PALADIN then - player:addItem(26189) - item = "incandescent crown" - end - if player:getVocation():getBaseId() == VOCATION.BASE_ID.KNIGHT then - player:addItem(26188) - item = "iron crown" + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission) < 1 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission, 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.AccessDoor, 1) end - player:addExperience(50000) - player:addItem(26186) - player:setStorageValue(Storage.CultsOfTibia.FinalBoss.Mission, 3) - player:sendTextMessage(MESSAGE_EXPERIENCE, "You gained 50000 experience points.") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You gained a mystery box.") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You gained a " .. item .. ".") - else - npcHandler:say( - "In wich of the following topics are you interested in? Cult of {Life}, \z - Cult of {Prosperity}, Cult of the {Minotaurs}, Cult of the {Barkless}, Cult of the {Misguided}, \z - Cult of {Orcs} or Cult of the {Humans}?", - npc, - creature - ) - npcHandler:setTopic(playerId, 2) + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission) == 2 then + npcHandler:say({ + "You have done our world a great favour and reason enough to be proud of yourself. ...", + "Although we could not rout out each and every cult and they will soon find another source to fuel their evil, we have dealt the enemy a vital blow that will take time and resources to recouperate from. ...", + "You have undoubtedly bought your world some valuable time and weakened the enemy. Take my thanks in behalf of the world and keep up your heroic work. For your reward you must have two free slots. Are you ready to receive it?", + }, npc, creature) + npcHandler:setTopic(playerId, 4) end - -- General elseif npcHandler:getTopic(playerId) == 2 then local missionsTable = config.missions[message:lower()] if missionsTable then @@ -501,28 +398,51 @@ local function creatureSayCallback(npc, creature, type, message) player:sendTextMessage(MESSAGE_EXPERIENCE, "You gained " .. rewardExperience[playerId] .. " experience points.") npcHandler:setTopic(playerId, 0) elseif player:getStorageValue(storage[playerId]) > 0 and player:getStorageValue(storage[playerId]) > value[playerId] then - npcHandler:say({ "You already done this mission." }, npc, creature) + npcHandler:say("You already done this mission.", npc, creature) npcHandler:setTopic(playerId, 2) else npcHandler:say(missionsTable.text, npc, creature) npcHandler:setTopic(playerId, 3) end end - -- Accept mission - elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 3 then - if player:getStorageValue(storage[playerId]) < 1 then - npcHandler:say("Very nice! Come back if you have found what's going on in this cult.", npc, creature) - player:setStorageValue(storage[playerId], 1) - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) + elseif MsgContains(message, "yes") then + if npcHandler:getTopic(playerId) == 3 then + if player:getStorageValue(storage[playerId]) < 1 then + npcHandler:say("Very nice! Come back if you have found what's going on in this cult.", npc, creature) + player:setStorageValue(storage[playerId], 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Questline, 1) + end + npcHandler:setTopic(playerId, 2) + elseif player:getStorageValue(storage[playerId]) > 0 then + npcHandler:say("You have not finished your work yet. Come back when you're done.", npc, creature) + npcHandler:setTopic(playerId, 2) end - npcHandler:setTopic(playerId, 2) - elseif player:getStorageValue(storage[playerId]) > 0 then - npcHandler:say("You have not finished your work yet. Come back when you're done.", npc, creature) - npcHandler:setTopic(playerId, 2) + elseif npcHandler:getTopic(playerId) == 4 then + local vocationRewards = { + [VOCATION.BASE_ID.SORCERER] = { itemId = 26190, itemName = "reflecting crown" }, + [VOCATION.BASE_ID.DRUID] = { itemId = 26187, itemName = "leaf crown" }, + [VOCATION.BASE_ID.PALADIN] = { itemId = 26189, itemName = "incandescent crown" }, + [VOCATION.BASE_ID.KNIGHT] = { itemId = 26188, itemName = "iron crown" }, + } + local vocationId = player:getVocation():getBaseId() + local reward = vocationRewards[vocationId] + local item = "" + if reward then + player:addItem(reward.itemId) + item = reward.itemName + end + player:addExperience(50000) + player:addItem(26186) + player:addAchievement("Corruption Contained") + player:sendTextMessage(MESSAGE_EXPERIENCE, "You gained 50000 experience points.") + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You gained a mystery box.") + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You gained a " .. item .. ".") + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission, 3) + npcHandler:say("Here's your reward. Thank you and farewell!", npc, creature) + npcHandler:setTopic(playerId, 0) end - -- Recuse mission - elseif MsgContains(message, "no") and npcHandler:getTopic(playerId) == 3 then + elseif MsgContains(message, "no") then npcHandler:say("What a pitty! You can come back, when ever you want, if you have changed your opinion.", npc, creature) npcHandler:setTopic(playerId, 0) end diff --git a/data-otservbr-global/npc/gnomus.lua b/data-otservbr-global/npc/gnomus.lua index f12104ca8e0..20b44ef0ba1 100644 --- a/data-otservbr-global/npc/gnomus.lua +++ b/data-otservbr-global/npc/gnomus.lua @@ -50,38 +50,7 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -local quantidade = {} - -local function greetCallback(npc, creature) - local player = Player(creature) - local playerId = player:getId() - - if player then - npcHandler:setMessage(MESSAGE_GREET, { "Greetings, member of the Bigfoot Brigade. We could really use some {help} from you right now. You should prove {worthy} to our alliance." }) - npcHandler:setTopic(playerId, 1) - end - return true -end - -keywordHandler:addKeyword({ "help" }, StdModule.say, { npcHandler = npcHandler, text = "If you're willing to help us, we could need an escort for arriving {ordnance}, help with {charting} the cave system and someone needs to get some heat {measurements} fast." }) -keywordHandler:addKeyword({ "worthy" }, StdModule.say, { - npcHandler = npcHandler, - text = { - "You're already known amongst the gnomes, member of the Bigfoot Brigade. I will make sure that the alliance learns of your deeds but you'll still need to help the dwarves and gnomes of this outpost to show your worth. ...", - "We also found {suspicious devices} carried by all kinds of creatures down here. Down here, they are of extreme worth to us since they could contain the key to what's happening all around us. ...", - "If you can aquire any, return them to me and I make sure to tell the others of your generosity. Return to me afterwards to check on your current {status}.", - }, -}) -keywordHandler:addKeyword({ "base" }, StdModule.say, { - npcHandler = npcHandler, - text = { "Gnomish supplies and ingenuity have helped to establish and fortify this outpost. ...", "Our knowledge of the enemy and it's tactics would be of more use if the dwarves would listen to us somewhat more. But gnomes have learned to live with the imperfection of the other races." }, -}) -keywordHandler:addKeyword({ "efforts" }, StdModule.say, { - npcHandler = npcHandler, - text = { "Our surveys of the area showed us some spikes in heat and seismic activity at very specific places. ...", "We conclude this is no coincidence and the enemy is using devices to pump up the lava to flood the area. We have seen it before and had to retreat each time. ...", "This time though we might have a counter prepared - given me manage to pierce their defences." }, -}) -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "My name is Gnomus." }) -keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I'm the main gnomish contact for this base. I coordinate our efforts with those of the dwarves to ensure everything is running smoothly." }) +local amount = {} local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) @@ -91,15 +60,14 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local time = configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN) + local time = 20 * 60 * 60 -- 20 hours - -- missão measurements - if MsgContains(message, "measurements") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskMeasurements) > 0 then -- Ainda não se passaram as 20h - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "measurements") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskMeasurements) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskMeasurements) <= 0 then -- Vai fazer a missão após 20h + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskMeasurements) <= 0 then npcHandler:say({ "The heat down here is not the only problem we have but one of our greatest concerns. Not only is it almost unbearable for us, it also seems to be rising. ...", "We need to find out if this is true and what that means for this place - and for us gnomes. You can help us do this by grabbing one of our trignometres and collecting as much as data from the heat in this area as possible. ...", @@ -107,47 +75,53 @@ local function creatureSayCallback(npc, creature, type, message) }, npc, creature) npcHandler:setTopic(playerId, 2) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) < 1 then -- Não possuía a missão, agora possui! + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) < 1 then npcHandler:say({ "The heat down here is not the only problem we have but one of our greatest concerns. Not only is it almost unbearable for us, it also seems to be rising. ...", "We need to find out if this is true and what that means for this place - and for us gnomes. You can help us do this by grabbing one of our trignometres and collecting as much as data from the heat in this area as possible. ...", "We'd need at least 5 measurements. Are you willing to do this?", }, npc, creature) npcHandler:setTopic(playerId, 2) - elseif (player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) == 1) and (player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) < 5) then -- Está na missão porém não terminou a task! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) < 5) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) - elseif player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) == 1 and player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) == 5 then -- Não possuía a missão, agora possui! - npcHandler:say({ "Excellent, you returned with more data! Let me see... hmm. ...", "Well, we need more data on this but first I will have to show this to our grand horticulturist. Thank you for getting this for us!" }, npc, creature) - player:setStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskMeasurements, os.time() + time) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) == 5 then + npcHandler:say({ + "Excellent, you returned with more data! Let me see... hmm. ...", + "Well, we need more data on this but first I will have to show this to our grand horticulturist. Thank you for getting this for us!", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskMeasurements, os.time() + time) player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Measurements, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements, 2) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "yes") then - npcHandler:say({ "How fortunate! There are some trignometres lying around next to that device behind me. Take one and hold it next to high temperature heat sources. ...", "If you gathered enough data, you will actually smell it from the device. ...", "Return to me with the results afterwards. Best of luck, we count on you!" }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say({ + "How fortunate! There are some trignometres lying around next to that device behind me. Take one and hold it next to high temperature heat sources. ...", + "If you gathered enough data, you will actually smell it from the device. ...", + "Return to me with the results afterwards. Best of luck, we count on you!", + }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Gnomes.Measurements, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartChest, 1) -- Permissão para usar o baú - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationA, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationB, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationC, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationD, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationE, 0) -- Garantindo que a task não inicie com -1 + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartChest, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationA, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationB, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationC, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationD, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationE, 0) npcHandler:setTopic(playerId, 1) end - -- missão ordnance - if MsgContains(message, "ordnance") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 3 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskOrdnance) > 0 then -- Ainda não se passaram as 20h - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "ordnance") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 3 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskOrdnance) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 3 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskOrdnance) <= 0 then -- Vai fazer a missão após 20h + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 3 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskOrdnance) <= 0 then npcHandler:say({ "I am constantly waiting for ordnance to arrive. A lot of gnomes intend to travel out here to help us but the main access path to our base is not safe anymore. ...", "Tragically we lost several gnomes after an outbreak of what I can only describe as a force from below. We were completely surprised by their onslaught and retreated to this outpost. ...", @@ -157,7 +131,7 @@ local function creatureSayCallback(npc, creature, type, message) }, npc, creature) npcHandler:setTopic(playerId, 22) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) < 1 then -- Não possuía a missão, agora possui! + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) < 1 then npcHandler:say({ "I am constantly waiting for ordnance to arrive. A lot of gnomes intend to travel out here to help us but the main access path to our base is not safe anymore. ...", "Tragically we lost several gnomes after an outbreak of what I can only describe as a force from below. We were completely surprised by their onslaught and retreated to this outpost. ...", @@ -166,47 +140,48 @@ local function creatureSayCallback(npc, creature, type, message) "Are you willing to help?", }, npc, creature) npcHandler:setTopic(playerId, 22) - elseif (player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 1) or (player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount) < 5) then -- Está na missão porém não terminou a task! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 1) or (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount) < 5) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) - elseif player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount) >= 5 then -- Não possuía a missão, agora possui! - if player:getStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount) >= 3 then - npcHandler:say({ "AMAZING! Not only did you salve all our friends - you also rescued the animals! Here is your reward and bonus! ...", "The other are already telling stories about you. Please return to me later if you want to help out some more!" }, npc, creature) - player:setStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskOrdnance, os.time() + time) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount) >= 5 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount) >= 3 then + npcHandler:say({ + "AMAZING! Not only did you salve all our friends - you also rescued the animals! Here is your reward and bonus! ...", + "The other are already telling stories about you. Please return to me later if you want to help out some more!", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskOrdnance, os.time() + time) player:addItem(27654, 2) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + 2) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Ordnance, 3) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, 3) else - npcHandler:say({ "The other are already telling stories about you. Please return to me later if you want to help out some more!" }, npc, creature) - player:setStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskOrdnance, os.time() + time) + npcHandler:say("The other are already telling stories about you. Please return to me later if you want to help out some more!", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskOrdnance, os.time() + time) player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Ordnance, 3) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, 3) end npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 22 and MsgContains(message, "yes") then - npcHandler:say( - { "Excellent, just follow the path to east until you reach a dead end, there is a hole that leads to a small cave underneath which will bring you right to the old trail. ...", "Help whoever you can and return them to the save cave exit - oh, and while you're at it... some of them will have pack animals. If you can rescue those as well, I'll hand you a bonus. Good luck!" }, - npc, - creature - ) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say({ + "Excellent, just follow the path to east until you reach a dead end, there is a hole that leads to a small cave underneath which will bring you right to the old trail. ...", + "Help whoever you can and return them to the save cave exit - oh, and while you're at it... some of them will have pack animals. If you can rescue those as well, I'll hand you a bonus. Good luck!", + }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Gnomes.Ordnance, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount, 0) -- Garantindo que a task não inicie com -1 + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount, 0) npcHandler:setTopic(playerId, 1) end - -- missão charting - if MsgContains(message, "charting") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskCharting) > 0 then -- Ainda não se passaram as 20h - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "charting") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskCharting) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) == 2 and player:getStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskCharting) <= 0 then -- Vai fazer a missão após 20h + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskCharting) <= 0 then npcHandler:say({ "While exploring these caves to find places to collect spores and grow mushrooms, we found several strange structures. I am convinced that this system was once home to intelligent beings. ...", "However, the creatures from below are now disturbing our research as well as some particularly pesky dwarves who just would not leave us alone. ...", @@ -215,7 +190,7 @@ local function creatureSayCallback(npc, creature, type, message) }, npc, creature) npcHandler:setTopic(playerId, 33) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) < 1 then -- Não possuía a missão, agora possui! + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) < 1 then npcHandler:say({ "While exploring these caves to find places to collect spores and grow mushrooms, we found several strange structures. I am convinced that this system was once home to intelligent beings. ...", "However, the creatures from below are now disturbing our research as well as some particularly pesky dwarves who just would not leave us alone. ...", @@ -223,21 +198,21 @@ local function creatureSayCallback(npc, creature, type, message) "I am especially interested in the scattered dark structures around these parts. Would you do that?", }, npc, creature) npcHandler:setTopic(playerId, 33) - elseif (player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) == 1) and (player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) < 3) then -- Está na missão porém não terminou a task! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) < 3) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) == 1 and player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) >= 3 then -- Não possuía a missão, agora possui! - npcHandler:say({ "Thank you very much! With those structures mapped out we will be able to complete the puzzle in no time!" }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) == 6 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) >= 3 then + npcHandler:say("Thank you very much! With those structures mapped out we will be able to complete the puzzle in no time!", npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) == 6 then player:addItem(27654, 2) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + 2) else player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + 1) end - player:setStorageValue(Storage.DangerousDepths.Gnomes.Charting, 2) - player:setStorageValue(Storage.DangerousDepths.Gnomes.TimeTaskCharting, os.time() + time) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TimeTaskCharting, os.time() + time) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 33 and MsgContains(message, "yes") then @@ -246,97 +221,123 @@ local function creatureSayCallback(npc, creature, type, message) "Take one from the stack here next to me and map as many structures as possible. However, we need at least three locations to make any sense of this ancient layout at all. ...", "If you manage to map one of each structure around these parts - I assume there must be at least two times as many around here - I will hand you a bonus!", }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Gnomes.Charting, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartPaper, 1) -- Permissão para usar o papel - player:setStorageValue(Storage.DangerousDepths.Gnomes.OldGate, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.TheGaze, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.LostRuin, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.Outpost, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.Bastion, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Gnomes.BrokenTower, 0) -- Garantindo que a task não inicie com -1 + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartPaper, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.OldGate, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TheGaze, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LostRuin, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Outpost, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Bastion, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.BrokenTower, 0) npcHandler:setTopic(playerId, 1) end + local plural = "" + if MsgContains(message, "suspicious devices") or MsgContains(message, "suspicious device") then - npcHandler:say({ "If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer? " }, npc, creature) + npcHandler:say("If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer? ", npc, creature) npcHandler:setTopic(playerId, 55) elseif npcHandler:getTopic(playerId) == 55 then - quantidade[playerId] = tonumber(message) - if quantidade[playerId] then - if quantidade[playerId] > 1 then + amount[playerId] = tonumber(message) + if amount[playerId] then + if amount[playerId] > 1 then plural = plural .. "s" end - npcHandler:say({ "You want to offer " .. quantidade[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) + npcHandler:say("You want to offer " .. amount[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 56) else - npcHandler:say({ "Don't waste my time." }, npc, creature) + npcHandler:say("Don't waste my time.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the gnomes mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the gnomes mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the dwarves mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the dwarves mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the scouts mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the scouts mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end end - -- Início checagem de pontos de tasks!! if MsgContains(message, "status") then - npcHandler:say({ "So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) + npcHandler:say("So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 5) elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points), 0) .. "/10)", npc, creature) end + return true end +keywordHandler:addKeyword({ "help" }, StdModule.say, { npcHandler = npcHandler, text = "If you're willing to help us, we could need an escort for arriving {ordnance}, help with {charting} the cave system and someone needs to get some heat {measurements} fast." }) +keywordHandler:addKeyword({ "worthy" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "You're already known amongst the gnomes, member of the Bigfoot Brigade. I will make sure that the alliance learns of your deeds but you'll still need to help the dwarves and gnomes of this outpost to show your worth. ...", + "We also found {suspicious devices} carried by all kinds of creatures down here. Down here, they are of extreme worth to us since they could contain the key to what's happening all around us. ...", + "If you can aquire any, return them to me and I make sure to tell the others of your generosity. Return to me afterwards to check on your current {status}.", + }, +}) +keywordHandler:addKeyword({ "base" }, StdModule.say, { npcHandler = npcHandler, text = { + "Gnomish supplies and ingenuity have helped to establish and fortify this outpost. ...", + "Our knowledge of the enemy and it's tactics would be of more use if the dwarves would listen to us somewhat more. But gnomes have learned to live with the imperfection of the other races.", +} }) +keywordHandler:addKeyword({ "efforts" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "Our surveys of the area showed us some spikes in heat and seismic activity at very specific places. ...", + "We conclude this is no coincidence and the enemy is using devices to pump up the lava to flood the area. We have seen it before and had to retreat each time. ...", + "This time though we might have a counter prepared - given me manage to pierce their defences.", + }, +}) +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "My name is Gnomus." }) +keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "I'm the main gnomish contact for this base. I coordinate our efforts with those of the dwarves to ensure everything is running smoothly." }) + +npcHandler:setMessage(MESSAGE_GREET, "Greetings, member of the Bigfoot Brigade. We could really use some {help} from you right now. You should prove {worthy} to our alliance.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) npcHandler:setCallback(CALLBACK_REMOVE_INTERACTION, onReleaseFocus) -npcHandler:setCallback(CALLBACK_GREET, greetCallback) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua index ce5c6737e02..bfc9000ca0f 100644 --- a/data-otservbr-global/npc/hireling.lua +++ b/data-otservbr-global/npc/hireling.lua @@ -420,11 +420,13 @@ function createHirelingType(HirelingName) local TOPIC_FOOD = { SKILL_CHOOSE = 1301, + SKILL_SURPRISE = 1302, } local GREETINGS = { BANK = "Alright! What can I do for you and your bank business, |PLAYERNAME|?", - FOOD = "Hmm, yes! A variety of fine food awaits! However, a small expense of 15000 gold is expected to make these delicious masterpieces happen. Shall I?", + FOOD = [[Hmm, yes! A variety of fine food awaits! However, a small expense of 15000 gold is expected to make these delicious masterpieces happen. + For 90000 gold I will also serve you a specific dish. Just tell me what it shall be: a {specific} meal or a little {surprise}.]], STASH = "Of course, here is your stash! Well-maintained and neatly sorted for your convenience!", } @@ -513,7 +515,7 @@ function createHirelingType(HirelingName) return message end - local function deliverFood(npc, creature, food_id) + local function deliverFood(npc, creature, food_id, cost) local playerId = creature:getId() local player = Player(creature) local itType = ItemType(food_id) @@ -523,8 +525,8 @@ function createHirelingType(HirelingName) npcHandler:say("Sorry, but you don't have enough capacity.", npc, creature) elseif not inbox or #inboxItems >= inbox:getMaxCapacity() then player:getPosition():sendMagicEffect(CONST_ME_POFF) - npcHandler:say("Sorry, you don't have enough room on your inbox", npc, creature) - elseif not player:removeMoneyBank(15000) then + npcHandler:say("Sorry, you don't have enough room on your inbox.", npc, creature) + elseif not player:removeMoneyBank(cost) then npcHandler:say("Sorry, you don't have enough money.", npc, creature) else local message = getDeliveredMessageByFoodId(food_id) @@ -534,38 +536,66 @@ function createHirelingType(HirelingName) npcHandler:setTopic(playerId, TOPIC.SERVICES) end - local function cookFood(npc, creature) + local function cookFood(npc, creature, specificRequest) local playerId = creature:getId() - local random = math.random(6) - if random == 6 then - -- ask for preferred skill + if specificRequest then + npcHandler:say("Very well. You may choose one of the following: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature) npcHandler:setTopic(playerId, TOPIC_FOOD.SKILL_CHOOSE) - npcHandler:say("Yay! I have the ingredients to make a skill boost dish. Would you rather like to boost your {magic}, {melee}, {shielding} or {distance} skill?", npc, creature) - else -- deliver the random generated index - deliverFood(npc, creature, HIRELING_FOODS_IDS[random]) + else + npcHandler:say("Alright, let me astonish you. Shall I?", npc, creature) + deliverFood(npc, creature, HIRELING_FOODS_IDS[math.random(#HIRELING_FOODS_IDS)], 15000) end end local function handleFoodActions(npc, creature, message) local playerId = creature:getId() + if npcHandler:getTopic(playerId) == TOPIC.FOOD then - if MsgContains(message, "yes") then - cookFood(npc, creature) + if MsgContains(message, "specific") then + npcHandler:setTopic(playerId, TOPIC_FOOD.SPECIFIC) + npcHandler:say("Which specific meal would you like? Choices are: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature) + elseif MsgContains(message, "surprise") then + local random = math.random(6) + if random == 6 then + npcHandler:setTopic(playerId, TOPIC_FOOD.SKILL_CHOOSE) + npcHandler:say("Yay! I have the ingredients to make a skill boost dish. Would you rather like to boost your {magic}, {melee}, {shielding}, or {distance} skill?", npc, creature) + else + deliverFood(npc, creature, HIRELING_FOODS_IDS[random], 15000) + end + elseif MsgContains(message, "yes") then + deliverFood(npc, creature, HIRELING_FOODS_IDS[math.random(#HIRELING_FOODS_IDS)], 15000) elseif MsgContains(message, "no") then npcHandler:setTopic(playerId, TOPIC.SERVICES) npcHandler:say("Alright then, ask me for other {services}, if you want.", npc, creature) end elseif npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE then if MsgContains(message, "magic") then - deliverFood(npc, creature, HIRELING_FOODS_BOOST.MAGIC) + deliverFood(npc, creature, HIRELING_FOODS_BOOST.MAGIC, 15000) elseif MsgContains(message, "melee") then - deliverFood(npc, creature, HIRELING_FOODS_BOOST.MELEE) + deliverFood(npc, creature, HIRELING_FOODS_BOOST.MELEE, 15000) elseif MsgContains(message, "shielding") then - deliverFood(npc, creature, HIRELING_FOODS_BOOST.SHIELDING) + deliverFood(npc, creature, HIRELING_FOODS_BOOST.SHIELDING, 15000) elseif MsgContains(message, "distance") then - deliverFood(npc, creature, HIRELING_FOODS_BOOST.DISTANCE) + deliverFood(npc, creature, HIRELING_FOODS_BOOST.DISTANCE, 15000) + else + npcHandler:say("Sorry, but you must choose a valid skill class. Would you like to boost your {magic}, {melee}, {shielding}, or {distance} skill?", npc, creature) + end + elseif npcHandler:getTopic(playerId) == TOPIC_FOOD.SPECIFIC then + local specificFoodOptions = { + ["chilli con carniphila"] = 29412, + ["svargrond salmon filet"] = 29413, + ["carrion casserole"] = 29414, + ["consecrated beef"] = 29415, + ["roasted wyvern wings"] = 29408, + ["carrot pie"] = 29409, + ["tropical marinated tiger"] = 29410, + ["delicatessen salad"] = 29411, + } + + if specificFoodOptions[message:lower()] then + deliverFood(npc, creature, specificFoodOptions[message:lower()], 90000) else - npcHandler:say("Sorry, but you must choose a valid skill class. Would you like to boost your {magic}, {melee}, {shielding} or {distance} skill?", npc, creature) + npcHandler:say("I'm sorry, but that's not a valid food option. Please choose from: {chilli con carniphila}, {svargrond salmon filet}, {carrion casserole}, {consecrated beef}, {roasted wyvern wings}, {carrot pie}, {tropical marinated tiger}, or {delicatessen salad}.", npc, creature) end end end @@ -656,7 +686,7 @@ function createHirelingType(HirelingName) end elseif npcHandler:getTopic(playerId) == TOPIC.BANK then enableBankSystem[playerId] = true - elseif npcHandler:getTopic(playerId) == TOPIC.FOOD or npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE then + elseif npcHandler:getTopic(playerId) == TOPIC.FOOD or npcHandler:getTopic(playerId) == TOPIC_FOOD.SKILL_CHOOSE or npcHandler:getTopic(playerId) == TOPIC_FOOD.SPECIFIC then handleFoodActions(npc, creature, message) elseif npcHandler:getTopic(playerId) == TOPIC.GOODS then -- Ensures players cannot access other shop categories diff --git a/data-otservbr-global/npc/ivalisse.lua b/data-otservbr-global/npc/ivalisse.lua index 71948ca4bb2..5b3e5a96140 100644 --- a/data-otservbr-global/npc/ivalisse.lua +++ b/data-otservbr-global/npc/ivalisse.lua @@ -50,16 +50,6 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end --- Don't forget npcHandler = npcHandler in the parameters. It is required for all StdModule functions! -keywordHandler:addKeyword({ "silus" }, StdModule.say, { npcHandler = npcHandler, text = "My {father}, can you tell me if he's alright?" }) -keywordHandler:addKeyword({ "thais" }, StdModule.say, { npcHandler = npcHandler, text = "Alright then, you are very welcome to explore the temple!" }) -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "My name is Ivalisse." }) -keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "There is always time to make a change." }) -keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "Besides my various {duties} in the temple, I also take care of visitors. Well, I would but right now I can't get my mind of how my {father}'s doing. I am sorry." }) -keywordHandler:addKeyword({ "duties" }, StdModule.say, { npcHandler = npcHandler, text = " I help linking the portals of this temple to other ancient sites of the {Astral Shapers}." }) -keywordHandler:addKeyword({ "duties" }, StdModule.say, { npcHandler = npcHandler, text = " I help linking the portals of this temple to other ancient sites of the {Astral Shapers}." }) -keywordHandler:addKeyword({ "mission" }, StdModule.say, { npcHandler = npcHandler, text = "Besides my various {duties} in the temple, I also take care of visitors. Well, I would but right now I can't get my mind of how my {father}'s doing. I am sorry." }) - local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -69,13 +59,12 @@ local function creatureSayCallback(npc, creature, type, message) end if MsgContains(message, "temple") then - npcHandler:say({ - "Well, I hope you like it here. We tried to rebuild in the {Shaper}'s will. I am a bit preoccupied at the moment because of the absence of my {father}. I may not be the best of help currently, sorry.", - }, npc, creature) + npcHandler:say("Well, I hope you like it here. We tried to rebuild in the {Shaper}'s will. I am a bit preoccupied at the moment because of the absence of my {father}. I may not be the best of help currently, sorry.", npc, creature) npcHandler:setTopic(playerId, 1) - end - - if MsgContains(message, "imbuing") or MsgContains(message, "imbuements") then + elseif MsgContains(message, "mission") then + npcHandler:say("Besides my various {duties} in the temple, I also take care of visitors. Well, I would but right now I can't get my mind of how my {father}'s doing. I am sorry.", npc, creature) + npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "imbuing") or MsgContains(message, "imbuements") then npcHandler:say({ "The astral Shapers had many ways to shape and refine weapons and equipment. They built shrines dedicated to this world's energies, focussing it and utilising it like a tool to enhance objects. ...", "They called this process imbuing and perfected it throughout time. Remains of these shrines are scattered all over Tibia. ...", @@ -85,62 +74,67 @@ local function creatureSayCallback(npc, creature, type, message) "We see the gates as an invitation, use them to your advantage and follow the ways of the Shapers. Access to one of these ancient shrines is the only way to learn additional imbuements. ...", "But beware, as far as we know, some of them have been claimed by other ancient beings and there is now way for us to prepare you what lies beyond any of those gates.", }, npc, creature) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "father") and npcHandler:getTopic(playerId) == 1 then + if player:getStorageValue(Storage.Quest.U8_54.TheNewFrontier.Questline) == 29 then + npcHandler:say({ + "Papa- my father has recently started an adventure on his own. His name is Silus; he is a member of the Edron academy. ...", + "Ever since he joined what he called a 'special research division', he went on and on about Zao and how venturing there would help him get ahead. ...", + "You must know he lives for science, especially concerning faraway lands and cultures. He talked about the importance of practical field studies but, frankly, he isn't particularly cut out for that. ...", + "I know he has to focus to get his research done right now, and I simply cannot leave my duties in the temple. You seem like a person who travels a lot; would you be willing to help me?", + }, npc, creature) + npcHandler:setTopic(playerId, 2) + elseif player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Ivalisse) == 1 or player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Chalice) == 1 then + npcHandler:say("Well, I hope you like it here. We tried to rebuild in the Shaper's will. I am a bit preoccupied at the moment because of the absence of my father. I may not be the best of help currently, sorry.", npc, creature) + npcHandler:setTopic(playerId, 0) + elseif player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.DragonkingKilled) >= 1 and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Ivalisse) < 1 then + npcHandler:say({ + "What? You're telling me you found father? How is he? What did papa say? A chalice? As a disguise? The whole time? ...", + "Well, I am not as much surprised as I am happy to hear that he's alright. You know, after the incident with the duck and the umbrella—it doesn't get to me that easily anymore. ...", + "Thank you very much for doing all this for me; I will be forever grateful. I have nothing to repay you with, but you are already blessed to have been able to lay eyes on the sacred Shaper ruins.", + }, npc, creature) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Ivalisse, 1) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "yes") then + if npcHandler:getTopic(playerId) == 2 then + npcHandler:say({ + "Thank you! He told me the other researchers in his team discovered a bridge leading to a cave with a dragon sculpture somewhere in a muggy, grassy area. ...", + "The cave is said to lead to a temple complex underground which is ued as a gathering place for a race called 'draken'. He left right away and tried to enter Zao on his own. ...", + "I was even more worried when he explained the route he chose. he wanted to head straight through a giant steppe and through a massive mountainous ridge to reach the grassy plains of lower Zao. ...", + "If you're interested: I know that the Shapers where active in all corners of Tibia. If you happen to find Shaper ruins there, you may even be able to gather some of their lost knowledge. ...", + "I may have been a bit stubborn and angry the day he left, I even refused to say farewell. And now I worry if he is safe. ...", + "I can not do much to help you but I can open a portal to get you quite close to his last known location in Zao. What do you say, will you help me find my father?", + }, npc, creature) + npcHandler:setTopic(playerId, 3) + elseif npcHandler:getTopic(playerId) == 3 then + npcHandler:say("You would? That's great! Thank you! If you can find my father, tell him I understand and that I really miss him!", npc, creature) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessFire, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Chalice, 1) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "no") then + npcHandler:say("Oh nevermind, I am sorry I asked you for this.", npc, creature) + npcHandler:setTopic(playerId, 0) end - if MsgContains(message, "father") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ - "Papa- my father has recently started an adventure on his own. His name is Silus, he is a member of the Edron academy. ...", - "Ever since he has joined what he called a 'special research division', he went on and on about Zao and how venturing there would help him get ahead. ...", - "You must know he lives for science, especially concerning far-away lands and cultures. He talked about the importance of practical field studies but, frankly, he isn't particularly cut out for that. ...", - "I know he has to focus to get his research done right now and I simply cannot leave my duties in the temple. You seem like a person who travels a lot, would you be willing to help me?", - }, npc, creature) - npcHandler:setTopic(playerId, 2) - elseif MsgContains(message, "father") and npcHandler:getTopic(playerId) == 1 and player:getStorageValue(Storage.ForgottenKnowledge.Ivalisse) == 1 or player:getStorageValue(Storage.ForgottenKnowledge.Chalice) == 1 then - npcHandler:say({ - "Well, I hope you like it here. We tried to rebuild in the Shaper's will. I am a bit preoccupied at the moment because of the absence of my father. I may not be the best of help currently, sorry.", - }, npc, creature) - elseif MsgContains(message, "father") and npcHandler:getTopic(playerId) == 1 and player:getStorageValue(Storage.ForgottenKnowledge.DragonkingKilled) == 1 then - npcHandler:say({ - "What? You're telling me you found father? How is he, what did papa say? A chalice? As a disguise? The whole time? ...", - "Well, I am not as much surprised as I am happy to hear that he's alright. You know, after the incident with the duck and the umbrella - it doesn't get to me that easily anymore. ...", - "Thank you very much for doing all this for me, I will be forever grateful. I have nothing to repay you with but you are already blessed to have been able to lay eyes on the sacred shaper ruins.", - }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.Ivalisse, 1) - end - - if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 2 then - npcHandler:say({ - "Thank you! He told me the other researchers in his team discovered a bridge leading to a cave with a dragon sculpture somewhere in a muggy, grassy area. ...", - "The cave is said to lead to a temple complex underground which is ued as a gathering place for a race called 'draken'. He left right away and tried to enter Zao on his own. ...", - "I was even more worried when he explained the route he chose. he wanted to head straight through a giant steppe and through a massive mountainous ridge to reach the grassy plains of lower Zao. ...", - "If you're interested: I know that the Shapers where active in all corners of Tibia. If you happen to find Shaper ruins there, you may even be able to gather some of their lost knowledge. ...", - "I may have been a bit stubborn and angry the day he left, I even refused to say farewell. And now I worry if he is safe. ...", - "I can not do much to help you but I can open a portal to get you quite close to his last known location in Zao. What do you say, will you help me find my father?", - }, npc, creature) - npcHandler:setTopic(playerId, 3) - elseif MsgContains(message, "no") and npcHandler:getTopic(playerId) == 2 then - npcHandler:say({ - "Oh nevermind, I am sorry I asked you for this.", - }, npc, creature) - end - - if MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 3 then - npcHandler:say({ - "You would? That's great! Thank you! If you can find my father, tell him I understand and that I really miss him!", - }, npc, creature) - player:setStorageValue(Storage.ForgottenKnowledge.AccessFire, 1) - player:setStorageValue(Storage.ForgottenKnowledge.Chalice, 1) - elseif MsgContains(message, "no") and npcHandler:getTopic(playerId) == 3 then - npcHandler:say({ - "Oh nevermind, I am sorry I asked you for this.", - }, npc, creature) - end return true end +npcHandler:setMessage(MESSAGE_GREET, "Hello, worshiper of the Astral Shapers! Welcome to the temple! While you are here to pay tribute, you can also learn something about the ancient art of imbuing.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Oh... farewell, child.") npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) + +-- Don't forget npcHandler = npcHandler in the parameters. It is required for all StdModule functions! +keywordHandler:addKeyword({ "silus" }, StdModule.say, { npcHandler = npcHandler, text = "My {father}, can you tell me if he's alright?" }) +keywordHandler:addKeyword({ "thais" }, StdModule.say, { npcHandler = npcHandler, text = "Alright then, you are very welcome to explore the temple!" }) +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "My name is Ivalisse." }) +keywordHandler:addKeyword({ "time" }, StdModule.say, { npcHandler = npcHandler, text = "There is always time to make a change." }) +keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "Besides my various {duties} in the temple, I also take care of visitors. Well, I would but right now I can't get my mind of how my {father}'s doing. I am sorry." }) +keywordHandler:addKeyword({ "duties" }, StdModule.say, { npcHandler = npcHandler, text = " I help linking the portals of this temple to other ancient sites of the {Astral Shapers}." }) +keywordHandler:addKeyword({ "duties" }, StdModule.say, { npcHandler = npcHandler, text = " I help linking the portals of this temple to other ancient sites of the {Astral Shapers}." }) + npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) -- npcType registering the npcConfig table diff --git a/data-otservbr-global/npc/iwar.lua b/data-otservbr-global/npc/iwar.lua index d30d368bf5a..b5238538ba9 100644 --- a/data-otservbr-global/npc/iwar.lua +++ b/data-otservbr-global/npc/iwar.lua @@ -49,12 +49,6 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -local function greetCallback(npc, creature) - local playerId = creature:getId() - - local player = Player(creature) - return true -end local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -63,23 +57,22 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local valorPicture = 10000 + local valuePicture = 10000 - -- Começou a quest - if MsgContains(message, "has the cat got your tongue?") and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 4 then - npcHandler:say({ "Nice. You like your picture, haa? Give me 10,000 gold and I will deliver it to the museum. Do you {pay}?" }, npc, creature) + if MsgContains(message, "has the cat got your tongue?") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 4 then + npcHandler:say("Nice. You like your picture, haa? Give me 10,000 gold and I will deliver it to the museum. Do you {pay}?", npc, creature) npcHandler:setTopic(playerId, 2) npcHandler:setTopic(playerId, 2) elseif MsgContains(message, "pay") or MsgContains(message, "yes") then if npcHandler:getTopic(playerId) == 2 then - if (player:getMoney() + player:getBankBalance()) >= valorPicture then - npcHandler:say({ "Well done. The picture will be delivered to the museum as last as possible." }, npc, creature) + if (player:getMoney() + player:getBankBalance()) >= valuePicture then + npcHandler:say("Well done. The picture will be delivered to the museum as last as possible.", npc, creature) npcHandler:setTopic(playerId, 0) npcHandler:setTopic(playerId, 0) - player:removeMoneyBank(valorPicture) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 5) + player:removeMoneyBank(valuePicture) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 5) else - npcHandler:say({ "You don't have enough money." }, npc, creature) + npcHandler:say("You don't have enough money.", npc, creature) npcHandler:setTopic(playerId, 1) npcHandler:setTopic(playerId, 1) end @@ -88,12 +81,12 @@ local function creatureSayCallback(npc, creature, type, message) return true end +npcHandler:setMessage(MESSAGE_GREET, "Hiho Storm Killer! Welcome to Kazordoon furniture store.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) npcHandler:setCallback(CALLBACK_REMOVE_INTERACTION, onReleaseFocus) -npcHandler:setCallback(CALLBACK_GREET, greetCallback) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/jamesfrancis.lua b/data-otservbr-global/npc/jamesfrancis.lua index bde27b5345d..bddde257b8b 100644 --- a/data-otservbr-global/npc/jamesfrancis.lua +++ b/data-otservbr-global/npc/jamesfrancis.lua @@ -23,25 +23,6 @@ npcConfig.flags = { floorchange = false, } -local function greetCallback(npc, creature) - local playerId = creature:getId() - - local player = Player(creature) - local playerId = player:getId() - - if player:getStorageValue(Storage.CultsOfTibia.Minotaurs.Access) < 1 then - npcHandler:setMessage(MESSAGE_GREET, "Gerimor is right. As an expert for minotaurs I am researching these creatures for years. I thought I already knew a lot but the monsters in this cave are {different}. It's a big {mystery}.") - npcHandler:setTopic(playerId, 1) - elseif (player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) >= 0 and player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) <= 50) and player:getStorageValue(Storage.CultsOfTibia.Minotaurs.Mission) < 3 then - npcHandler:setMessage(MESSAGE_GREET, "How is your {mission} going?") - npcHandler:setTopic(playerId, 5) - elseif player:getStorageValue(Storage.CultsOfTibia.Minotaurs.Mission) == 4 then - npcHandler:setMessage(MESSAGE_GREET, { "You say the minotaurs were controlled by a very powerful boss they worshipped. This explains why they had so much more power than the normal ones. ...", "I'm very thankful. Please go to the Druid of Crunor and tell him what you've seen. He might be interested in that." }) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.Mission, 5) - npcHandler:setTopic(playerId, 10) - end - return true -end npcConfig.voices = { interval = 15000, chance = 50, @@ -75,6 +56,28 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end +local function greetCallback(npc, creature) + local player = Player(creature) + local playerId = player:getId() + + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission) < 1 then + npcHandler:setMessage(MESSAGE_GREET, "Gerimor is right. As an expert for minotaurs I am researching these creatures for years. I thought I already knew a lot but the monsters in this cave are {different}. It's a big {mystery}.") + npcHandler:setTopic(playerId, 0) + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask) <= 50 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission) < 3 then + npcHandler:setMessage(MESSAGE_GREET, "How is your {mission} going?") + npcHandler:setTopic(playerId, 0) + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission) == 4 then + npcHandler:setMessage(MESSAGE_GREET, { + "You say the minotaurs were controlled by a very powerful boss they worshipped. This explains why they had so much more power than the normal ones. ...", + "I'm very thankful. Please go to the Druid of Crunor and tell him what you've seen. He might be interested in that.", + }) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, 5) + npcHandler:setTopic(playerId, 0) + end + + return true +end + local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -83,34 +86,30 @@ local function creatureSayCallback(npc, creature, type, message) return false end - -- Start quest - if MsgContains(message, "mystery") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ "The minotaurs I faced in the cave are much stronger than the normal ones. What I were able to see before I had to flee: all of them seem to belong to a cult worshipping their god. Could you do me a {favour}?" }, npc, creature) + if MsgContains(message, "mystery") then + npcHandler:say("The minotaurs I faced in the cave are much stronger than the normal ones. What I were able to see before I had to flee: all of them seem to belong to a cult worshipping their god. Could you do me a {favour}?", npc, creature) npcHandler:setTopic(playerId, 2) elseif MsgContains(message, "favour") and npcHandler:getTopic(playerId) == 2 then - npcHandler:say({ "I'd like to work in this cave researching the minotaurs. But right now there are too many of hem and what is more, they are too powerful for me. Could you enter the cave and kill at least 50 of these creatures?" }, npc, creature) + npcHandler:say("I'd like to work in this cave researching the minotaurs. But right now there are too many of hem and what is more, they are too powerful for me. Could you enter the cave and kill at least 50 of these creatures?", npc, creature) npcHandler:setTopic(playerId, 3) - elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 3 then - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) - end - npcHandler:say({ "Very nice. Return to me if you've finished your job." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.Mission, 2) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, 0) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.EntranceAccessDoor, 1) - npcHandler:setTopic(playerId, 0) - -- Delivering the quest - elseif MsgContains(message, "mission") and npcHandler:getTopic(playerId) == 5 then - if player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) >= 50 then - npcHandler:say({ "Great job! You have killed at least 50 of these monsters. I give this key to you to open the door to the inner area. Go there and find out what's going on." }, npc, creature) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.Mission, 3) - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.AccessDoor, 1) + elseif MsgContains(message, "mission") then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask) >= 50 then + npcHandler:say("Great job! You have killed at least 50 of these monsters. I give this key to you to open the door to the inner area. Go there and find out what's going on.", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.BossAccessDoor, 1) npcHandler:setTopic(playerId, 0) else - npcHandler:say({ "Come back when you have killed enough minotaurs." }, npc, creature) + npcHandler:say("Come back when you have killed enough minotaurs.", npc, creature) npcHandler:setTopic(playerId, 0) end + elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 3 then + npcHandler:say("Very nice. Return to me if you've finished your job.", npc, creature) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, 2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask, 0) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.AccessDoor, 1) + npcHandler:setTopic(playerId, 0) end + return true end diff --git a/data-otservbr-global/npc/kais.lua b/data-otservbr-global/npc/kais.lua index d7fe97f0e75..5da84b1d9cf 100644 --- a/data-otservbr-global/npc/kais.lua +++ b/data-otservbr-global/npc/kais.lua @@ -46,8 +46,8 @@ npcType.onCloseChannel = function(npc, creature) end -- Blood of the Mountain -local blessKeyword = keywordHandler:addKeyword({ "blood" }, StdModule.say, { npcHandler = npcHandler, text = "Would you like to receive that protection for a sacrifice of |BLESSCOST| gold, child?" }) -blessKeyword:addChildKeyword({ "yes" }, StdModule.bless, { npcHandler = npcHandler, text = "So receive the Blood of the Mountain, pilgrim.", cost = "|BLESSCOST|", bless = 7 }) +local blessKeyword = keywordHandler:addKeyword({ "enhanced" }, StdModule.say, { npcHandler = npcHandler, text = "I have the power to grant you the blood of the mountain's blessing. But I must ask of you to sacrifice |BLESSCOST| gold. Are you prepared for that?" }) +blessKeyword:addChildKeyword({ "yes" }, StdModule.bless, { npcHandler = npcHandler, text = "So receive the blood of the mountain, master.", cost = "|BLESSCOST|", bless = 8 }) blessKeyword:addChildKeyword({ "" }, StdModule.say, { npcHandler = npcHandler, text = "Fine. You are free to decline my offer.", reset = true }) -- Healing @@ -58,6 +58,7 @@ local function addHealKeyword(text, condition, effect) player:removeCondition(condition) player:getPosition():sendMagicEffect(effect) end) + keywordHandler:addAliasKeyword({ "help" }) end addHealKeyword("You are burning. Let me quench those flames.", CONDITION_FIRE, CONST_ME_MAGIC_GREEN) @@ -74,26 +75,19 @@ end, function(player) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) end) keywordHandler:addKeyword({ "heal" }, StdModule.say, { npcHandler = npcHandler, text = "You aren't looking that bad. Sorry, I can't help you. But if you are looking for additional protection you should go on the {pilgrimage} of ashes or get the protection of the {twist of fate} here." }) +keywordHandler:addAliasKeyword({ "help" }) -- Basic -keywordHandler:addKeyword({ "pilgrimage" }, StdModule.say, { npcHandler = npcHandler, text = "Whenever you receive a lethal wound, your vital force is damaged and there is a chance that you lose some of your equipment. With every single of the five {blessings} you have, this damage and chance of loss will be reduced." }) -keywordHandler:addKeyword({ "blessings" }, StdModule.say, { npcHandler = npcHandler, text = "There are five blessings available in five sacred places: the {spiritual} shielding, the spark of the {phoenix}, the {embrace} of Tibia, the fire of the {suns} and the wisdom of {solitude}. Additionally, you can receive the {twist of fate} here." }) -keywordHandler:addKeyword({ "spiritual" }, StdModule.say, { npcHandler = npcHandler, text = "I see you received the spiritual shielding in the whiteflower temple south of Thais." }, function(player) - return player:hasBlessing(1) -end) -keywordHandler:addAliasKeyword({ "shield" }) -keywordHandler:addKeyword({ "suns" }, StdModule.say, { npcHandler = npcHandler, text = "I can see you received the blessing of the two suns in the suntower near Ab'Dendriel." }, function(player) - return player:hasBlessing(3) -end) -keywordHandler:addAliasKeyword({ "fire" }) -keywordHandler:addKeyword({ "phoenix" }, StdModule.say, { npcHandler = npcHandler, text = "I can sense that the spark of the phoenix already was given to you by the dwarven priests of earth and fire in Kazordoon." }, function(player) - return player:hasBlessing(4) -end) -keywordHandler:addAliasKeyword({ "spark" }) -keywordHandler:addKeyword({ "solitude" }, StdModule.say, { npcHandler = npcHandler, text = "I can sense you already talked to the hermit Eremo on the isle of Cormaya and received this blessing." }, function(player) - return player:hasBlessing(5) -end) -keywordHandler:addAliasKeyword({ "wisdom" }) +keywordHandler:addKeyword({ "Kais" }, StdModule.say, { npcHandler = npcHandler, text = "I am Kais, Kais the Bound. Eternally {fixed} to the wretched place, unless... unless I prove my worth in aiding all those who seek my {help}." }) + +keywordHandler:addKeyword({ "pilgrimage" }, StdModule.say, { npcHandler = npcHandler, text = "Well, as I am quite in a fix currently, my only hope to escape this situation may be to grant you {healing} or an {enhanced} blessing if you wish. You must desire SOMETHING, right? Sure you do." }) +keywordHandler:addAliasKeyword({ "job" }) + +keywordHandler:addKeyword({ "blessing" }, StdModule.say, { + npcHandler = npcHandler, + text = "Besides the {enhanced} blessing available from me, I know of one other, granted by a solitary {nomad} far west of Svargrond. There are also five different other blessings available, each in a sacred place. ...\nThese blessings are: the {spiritual} shielding, the spark of the {phoenix}, the {embrace} of Tibia, the fire of the {suns} and the wisdom of {solitude}.", +}) + keywordHandler:addKeyword({ "spiritual" }, StdModule.say, { npcHandler = npcHandler, text = "You can ask for the blessing of spiritual shielding in the whiteflower temple south of Thais." }) keywordHandler:addAliasKeyword({ "shield" }) keywordHandler:addKeyword({ "suns" }, StdModule.say, { npcHandler = npcHandler, text = "You can ask for the blessing of the two suns in the suntower near Ab'Dendriel." }) @@ -102,10 +96,14 @@ keywordHandler:addKeyword({ "phoenix" }, StdModule.say, { npcHandler = npcHandle keywordHandler:addAliasKeyword({ "spark" }) keywordHandler:addKeyword({ "solitude" }, StdModule.say, { npcHandler = npcHandler, text = "Talk to the hermit Eremo on the isle of Cormaya about this blessing." }) keywordHandler:addAliasKeyword({ "wisdom" }) +keywordHandler:addKeyword({ "embrace" }, StdModule.say, { npcHandler = npcHandler, text = "The druids north of Carlin will provide you with the embrace of Tibia." }) +keywordHandler:addAliasKeyword({ "tibia" }) + +keywordHandler:addKeyword({ "nomad" }, StdModule.say, { npcHandler = npcHandler, text = "I know everyone and everything. It is certain that there is another enhanced blessing, the 'heart of the mountain'. Talk to a nomad far to the west of Svargrond, hiding slightly above ground." }) -npcHandler:setMessage(MESSAGE_GREET, "Welcome, noble |PLAYERNAME|") -npcHandler:setMessage(MESSAGE_WALKAWAY, "Good Bye, noble |PLAYERNAME|") -npcHandler:setMessage(MESSAGE_FAREWELL, "Good Bye, noble |PLAYERNAME|") +npcHandler:setMessage(MESSAGE_GREET, "Hmm... surely you are in need of {help} - will you let me? I am {Kais} the Bound and I can lend you a hand in {healing} your body and soul or even grant an {enhanced} blessing!") +npcHandler:setMessage(MESSAGE_WALKAWAY, "Fare you well... |PLAYERNAME|") +npcHandler:setMessage(MESSAGE_FAREWELL, "Fare you well... |PLAYERNAME|") npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/kizar.lua b/data-otservbr-global/npc/kizar.lua new file mode 100644 index 00000000000..df58dd82d3a --- /dev/null +++ b/data-otservbr-global/npc/kizar.lua @@ -0,0 +1,56 @@ +local internalNpcName = "Kizar" +local npcType = Game.createNpcType(internalNpcName) +local npcConfig = {} + +npcConfig.name = internalNpcName +npcConfig.description = internalNpcName + +npcConfig.health = 100 +npcConfig.maxHealth = npcConfig.health +npcConfig.walkInterval = 2000 +npcConfig.walkRadius = 2 + +npcConfig.outfit = { + lookType = 132, + lookHead = 114, + lookBody = 68, + lookLegs = 19, + lookFeet = 115, + lookAddons = 0, +} + +npcConfig.flags = { + floorchange = false, +} + +local keywordHandler = KeywordHandler:new() +local npcHandler = NpcHandler:new(keywordHandler) + +npcType.onThink = function(npc, interval) + npcHandler:onThink(npc, interval) +end + +npcType.onAppear = function(npc, creature) + npcHandler:onAppear(npc, creature) +end + +npcType.onDisappear = function(npc, creature) + npcHandler:onDisappear(npc, creature) +end + +npcType.onMove = function(npc, creature, fromPosition, toPosition) + npcHandler:onMove(npc, creature, fromPosition, toPosition) +end + +npcType.onSay = function(npc, creature, type, message) + npcHandler:onSay(npc, creature, type, message) +end + +npcType.onCloseChannel = function(npc, creature) + npcHandler:onCloseChannel(npc, creature) +end + +npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) + +-- npcType registering the npcConfig table +npcType:register(npcConfig) diff --git a/data-otservbr-global/npc/klom_stonecutter.lua b/data-otservbr-global/npc/klom_stonecutter.lua index 8f238b65a29..5c67133cc75 100644 --- a/data-otservbr-global/npc/klom_stonecutter.lua +++ b/data-otservbr-global/npc/klom_stonecutter.lua @@ -23,6 +23,15 @@ npcConfig.flags = { floorchange = false, } +npcConfig.voices = { + interval = 15000, + chance = 50, + { text = "Ah." }, + { text = "We need more volunteers!" }, + { text = 'And they call this "deep"...' }, + { text = "Preparation is paramount." }, +} + local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) @@ -50,51 +59,8 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -npcConfig.voices = { - interval = 15000, - chance = 50, - { text = "Ah." }, - { text = "We need more volunteers!" }, - { text = 'And they call this "deep"...' }, - { text = "Preparation is paramount." }, -} - local count = {} -local function greetCallback(npc, creature) - local player = Player(creature) - local playerId = player:getId() - - if player then - npcHandler:setMessage(MESSAGE_GREET, { - "Greetings. A warning straight ahead: I don't like loiterin'. If you're not here to {help} us, you're here to waste my time. Which I consider loiterin'. Now, try and prove your {worth} to our alliance. ... ", - "I have sealed some of the areas far too dangerous for anyone to enter. If you can prove you're capable, you'll get an opportunity to help destroy the weird machines, pumping lava into the caves leading to the most dangerous enemies.", - }, 2000) - npcHandler:setTopic(playerId, 1) - end - return true -end - -keywordHandler:addKeyword({ "help" }, StdModule.say, { npcHandler = npcHandler, text = "Well, the biggest problem we need to address are the ever charging {subterraneans} around here. And on top of that, there's the threat of the Lost, who quite made themselves at {home} in these parts." }) -keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "Maintainin' this whole operation, the dwarven involvement 'course. Don't know about them gnomes but if I ain't gettin' those dwarves in line, there'll be chaos down here. I also oversee the {defences} and {counterattacks}." }) -keywordHandler:addKeyword({ "defences" }, StdModule.say, { - npcHandler = npcHandler, - text = { - "The attacks of the enemy forces are fierce but we hold our ground. ... ", - "I'd love to face one of their generals in combat but as their masters they cowardly hide far behind enemy lines and I have other duties to fulfil. ... ", - "I envy you for the chance to thrust into the heart of the enemy, locking weapons with their jaws... or whatever... and see the fear in their eyes when they recognise they were bested.", - }, -}) -keywordHandler:addKeyword({ "counterattacks" }, StdModule.say, { - npcHandler = npcHandler, - text = { "I welcome a fine battle as any dwarf worth his beard should do. As long as it's a battle against something I can hit with my trusty axe. ...", "But here the true {enemy} eludes us. We fight wave after wave of their lackeys and if the gnomes are right the true enemy is up to something far more sinister. " }, -}) -keywordHandler:addKeyword({ "enemy" }, StdModule.say, { - npcHandler = npcHandler, - text = { "I have no idea what kind of creeps are behind all this. Even the gnomes don't and they have handled that stuff way more often. ...", "But even if we knew nothing more about them, the fact alone that they employ the help of those mockeries of all things dwarfish, marks them as an enemy of the dwarves and it's our obligation to annihilate them." }, -}) -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "Klom Stonecutter's the name. " }) - local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -103,103 +69,100 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local time = configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN) + local time = 20 * 60 * 60 -- 20 hours - -- missão subterraneans - if MsgContains(message, "subterraneans") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) == 2 and player:getStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskSubterranean) > 0 then - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "subterraneans") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskSubterranean) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) == 2 and player:getStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskSubterranean) <= 0 then - npcHandler:say({ "Vermin. Everywhere. We get a lot of strange four-legged crawlers and worms down here lately. It's getting out of hand and... well, I need a real killer for this. ", "Prepared to get rid of some seriously foul creepers for us?" }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskSubterranean) <= 0 then + npcHandler:say({ + "Vermin. Everywhere. We get a lot of strange four-legged crawlers and worms down here lately. It's getting out of hand and... well, I need a real killer for this. ", + "Prepared to get rid of some seriously foul creepers for us?", + }, npc, creature) npcHandler:setTopic(playerId, 2) end - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) < 1 then -- Não possuía a missão, agora possui! - npcHandler:say({ "Vermin. Everywhere. We get a lot of strange four-legged crawlers and worms down here lately. It's getting out of hand and... well, I need a real killer for this. ", "Prepared to get rid of some seriously foul creepers for us?" }, npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) < 1 then + npcHandler:say({ + "Vermin. Everywhere. We get a lot of strange four-legged crawlers and worms down here lately. It's getting out of hand and... well, I need a real killer for this. ", + "Prepared to get rid of some seriously foul creepers for us?", + }, npc, creature) npcHandler:setTopic(playerId, 2) - elseif (player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) == 1) and (player:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms) < 50) then -- Está na missão porém não terminou a task! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms) < 50) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) - elseif (player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) == 1) and (player:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms) >= 50) then - npcHandler:say({ "I'l say I'm blown away but a Klom Stonecutter is not that easily impressed. Still, your got your hands dirt for us and I appreciate that." }, npc, creature) - -- Entregando surprise jar + 1 ponto de missão! - player:setStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskSubterranean, os.time() + time) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms) >= 50) then + npcHandler:say("I'l say I'm blown away but a Klom Stonecutter is not that easily impressed. Still, your got your hands dirt for us and I appreciate that.", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskSubterranean, os.time() + time) player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + 1) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Subterranean, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean, 2) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "yes") then - npcHandler:say({ "Alright, good. Those things are strolling about and I ain't gonna have that. If it moves more than two legs, destroy it. If it moves legs and tentacles, destroy it again." }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say("Alright, good. Those things are strolling about and I ain't gonna have that. If it moves more than two legs, destroy it. If it moves legs and tentacles, destroy it again.", npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Dwarves.Subterranean, 1) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, 0) -- Garantindo que a task não inicie com -1 - npcHandler:setTopic(playerId, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms, 0) npcHandler:setTopic(playerId, 1) end - -- missão home - if MsgContains(message, "home") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 2 and player:getStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskHome) > 0 then - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "home") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskHome) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 2 and player:getStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskHome) <= 0 then - npcHandler:say( - { "We need to find a way to drive off the exiles from these caves. Countless makeshift homes are popping up at every corner. Destroy them and get the Lost out of hiding to eliminate them. ... ", "If you can capture a few of them, you'll receive a bonus. Just bring 'em to the border of our outpost and we will take care of the rest. ... ", "Are you ready for that? " }, - npc, - creature - ) - npcHandler:setTopic(playerId, 22) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskHome) <= 0 then + npcHandler:say({ + "We need to find a way to drive off the exiles from these caves. Countless makeshift homes are popping up at every corner. Destroy them and get the Lost out of hiding to eliminate them. ... ", + "If you can capture a few of them, you'll receive a bonus. Just bring 'em to the border of our outpost and we will take care of the rest. ... ", + "Are you ready for that? ", + }, npc, creature) npcHandler:setTopic(playerId, 22) end - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) < 1 then -- Não possuía a missão, agora possui! - npcHandler:say( - { "We need to find a way to drive off the exiles from these caves. Countless makeshift homes are popping up at every corner. Destroy them and get the Lost out of hiding to eliminate them. ... ", "If you can capture a few of them, you'll receive a bonus. Just bring 'em to the border of our outpost and we will take care of the rest. ... ", "Are you ready for that? " }, - npc, - creature - ) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) < 1 then + npcHandler:say({ + "We need to find a way to drive off the exiles from these caves. Countless makeshift homes are popping up at every corner. Destroy them and get the Lost out of hiding to eliminate them. ... ", + "If you can capture a few of them, you'll receive a bonus. Just bring 'em to the border of our outpost and we will take care of the rest. ... ", + "Are you ready for that? ", + }, npc, creature) npcHandler:setTopic(playerId, 22) - npcHandler:setTopic(playerId, 22) - elseif (player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) < 20 and player:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) < 3) then -- Está na missão porém não terminou nenhuma das tasks! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles) < 20 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) < 3) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) - elseif (player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) >= 20 and player:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) < 3) then - npcHandler:say({ "So you did it. Well, that won't be the last of 'em but this sure helps our situation down here. Return to me later if you want to help me again!" }, npc, creature) -- Caso não tenha feito o task bônus - -- Entregando surprise jar + 1 ponto de missão! - player:setStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskHome, os.time() + time) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Home, 2) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles) >= 20 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) < 3) then + npcHandler:say("So you did it. Well, that won't be the last of 'em but this sure helps our situation down here. Return to me later if you want to help me again!", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskHome, os.time() + time) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home, 2) player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + 1) - npcHandler:setTopic(playerId, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + 1) npcHandler:setTopic(playerId, 1) - elseif (player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) >= 20 and player:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) >= 3) then - npcHandler:say({ "So you did it. And you even made prisoners, the bonus is yours! Well, that won't be the last of 'em but this sure helps our situation down here. Return to me later if you want to help me again!" }, npc, creature) -- Se tiver feito ambas - -- Entregando 2 surprise jars + 2 pontos de missão! - player:setStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskHome, os.time() + time) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Home, 2) - player:addItem(27654, 2) -- +1 item pela task bônus! - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + 2) -- +1 ponto pela task bônus! + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles) >= 20 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) >= 3) then + npcHandler:say("So you did it. And you even made prisoners, the bonus is yours! Well, that won't be the last of 'em but this sure helps our situation down here. Return to me later if you want to help me again!", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskHome, os.time() + time) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home, 2) + player:addItem(27654, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + 2) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 22 and MsgContains(message, "yes") then - npcHandler:say({ "Very well, now try to find some of their makeshift homes and tear'em down. There's bound to be some stragglers you can 'persuade' to surrender, eliminate any resistance. Get back here when you're done." }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say("Very well, now try to find some of their makeshift homes and tear'em down. There's bound to be some stragglers you can 'persuade' to surrender, eliminate any resistance. Get back here when you're done.", npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Dwarves.Home, 1) - player:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Dwarves.Prisoners, 0) -- Garantindo que a task não inicie com -1 - npcHandler:setTopic(playerId, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners, 0) npcHandler:setTopic(playerId, 1) end local plural = "" + if MsgContains(message, "suspicious devices") or MsgContains(message, "suspicious device") then - npcHandler:say({ "If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer? " }, npc, creature) + npcHandler:say("If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer?", npc, creature) npcHandler:setTopic(playerId, 55) elseif npcHandler:getTopic(playerId) == 55 then count[playerId] = tonumber(message) @@ -207,68 +170,97 @@ local function creatureSayCallback(npc, creature, type, message) if count[playerId] > 1 then plural = plural .. "s" end - npcHandler:say({ "You want to offer " .. count[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) + npcHandler:say("You want to offer " .. count[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 56) else - npcHandler:say({ "Don't waste my time." }, npc, creature) + npcHandler:say("Don't waste my time.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 56 then if player:getItemCount(30888) >= count[playerId] then - npcHandler:say({ "Done." }, npc, creature) + npcHandler:say("Done.", npc, creature) if count[playerId] > 1 then plural = plural .. "s" end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. count[playerId] .. " point" .. plural .. " on the gnomes mission.") player:removeItem(30888, count[playerId]) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + count[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + count[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 56 then if player:getItemCount(30888) >= count[playerId] then - npcHandler:say({ "Done." }, npc, creature) + npcHandler:say("Done.", npc, creature) if count[playerId] > 1 then plural = plural .. "s" end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. count[playerId] .. " point" .. plural .. " on the dwarves mission.") player:removeItem(30888, count[playerId]) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + count[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + count[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 56 then if player:getItemCount(30888) >= count[playerId] then - npcHandler:say({ "Done." }, npc, creature) + npcHandler:say("Done.", npc, creature) if count[playerId] > 1 then plural = plural .. "s" end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. count[playerId] .. " point" .. plural .. " on the scouts mission.") player:removeItem(30888, count[playerId]) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + count[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + count[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end end - -- Início checagem de pontos de tasks!! if MsgContains(message, "status") then - npcHandler:say({ "So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) - npcHandler:setTopic(playerId, 5) + npcHandler:say("So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 5) elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points), 0) .. "/10)", npc, creature) end + return true end +keywordHandler:addKeyword({ "help" }, StdModule.say, { npcHandler = npcHandler, text = "Well, the biggest problem we need to address are the ever charging {subterraneans} around here. And on top of that, there's the threat of the Lost, who quite made themselves at {home} in these parts." }) +keywordHandler:addKeyword({ "job" }, StdModule.say, { npcHandler = npcHandler, text = "Maintainin' this whole operation, the dwarven involvement 'course. Don't know about them gnomes but if I ain't gettin' those dwarves in line, there'll be chaos down here. I also oversee the {defences} and {counterattacks}." }) +keywordHandler:addKeyword({ "defences" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "The attacks of the enemy forces are fierce but we hold our ground. ... ", + "I'd love to face one of their generals in combat but as their masters they cowardly hide far behind enemy lines and I have other duties to fulfil. ... ", + "I envy you for the chance to thrust into the heart of the enemy, locking weapons with their jaws... or whatever... and see the fear in their eyes when they recognise they were bested.", + }, +}) +keywordHandler:addKeyword({ "counterattacks" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "I welcome a fine battle as any dwarf worth his beard should do. As long as it's a battle against something I can hit with my trusty axe. ...", + "But here the true {enemy} eludes us. We fight wave after wave of their lackeys and if the gnomes are right the true enemy is up to something far more sinister. ", + }, +}) +keywordHandler:addKeyword({ "enemy" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "I have no idea what kind of creeps are behind all this. Even the gnomes don't and they have handled that stuff way more often. ...", + "But even if we knew nothing more about them, the fact alone that they employ the help of those mockeries of all things dwarfish, marks them as an enemy of the dwarves and it's our obligation to annihilate them.", + }, +}) +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "Klom Stonecutter's the name. " }) + +npcHandler:setMessage(MESSAGE_GREET, { + "Greetings. A warning straight ahead: I don't like loiterin'. If you're not here to {help} us, you're here to waste my time. Which I consider loiterin'. Now, try and prove your {worth} to our alliance. ... ", + "I have sealed some of the areas far too dangerous for anyone to enter. If you can prove you're capable, you'll get an opportunity to help destroy the weird machines, pumping lava into the caves leading to the most dangerous enemies.", +}) npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) diff --git a/data-otservbr-global/npc/lardoc_bashsmite.lua b/data-otservbr-global/npc/lardoc_bashsmite.lua index 79fbd410d6e..11367640ded 100644 --- a/data-otservbr-global/npc/lardoc_bashsmite.lua +++ b/data-otservbr-global/npc/lardoc_bashsmite.lua @@ -50,37 +50,7 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -local quantidade = {} - -local function greetCallback(npc, creature) - local player = Player(creature) - local playerId = player:getId() - - if player then - npcHandler:setMessage(MESSAGE_GREET, { "Since you are obviously not one of my relatives who pays me a long overdue visit, we should get {work} right away. We'll see if you can prove your {worth} to our alliance." }) - npcHandler:setTopic(playerId, 1) - end - return true -end - -keywordHandler:addKeyword({ "work" }, StdModule.say, { npcHandler = npcHandler, text = "Here's the situation: a tide of hazardous bugs, the gnomes named them {diremaws}, threatens our base. Then there is some kind of {growth} which seems connected to them somehow. We need to get rid of both." }) -keywordHandler:addKeyword({ "worth" }, StdModule.say, { - npcHandler = npcHandler, - text = { - "You're already known amongst the gnomes, member of the Bigfoot Brigade. I will make sure that the alliance learns of your deeds but you'll still need to help the dwarves and gnomes of this outpost to show your worth. ...", - "We also found suspicious devices carried by all kinds of creatures down here. Down here, they are of extreme worth to us since they could contain the key to what's happening all around us. ... ", - "If you can aquire any, return them to me and I make sure to tell the others of your generosity. Return to me afterwards to check on your current {status}.", - }, -}) -keywordHandler:addKeyword({ "job" }, StdModule.say, { - npcHandler = npcHandler, - text = { - "Leading the charge! It's a war down here. I maintain the outer defences and supplies which are organised back in Kazordoon and also by the gnomes. ...", - "I have sealed some of the areas far too dangerous for anyone to enter. If you can prove you're capable, you'll get an oportunity to help destroying the weird machines, pumping lava into the caves leading to the most dangerous enemies.", - "But even if we knew nothing more about them, the fact alone that they employ the help of those mockeries of all things dwarfish, marks them as an enemy of the dwarves and it's our obligation to annihilate them.", - }, -}) -keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "Bashsmite. That's all you need to know." }) +local amount = {} local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) @@ -90,15 +60,14 @@ local function creatureSayCallback(npc, creature, type, message) return false end - local tempo = configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN) + local time = 20 * 60 * 60 -- 20 hours - -- missão diremaws - if MsgContains(message, "diremaws") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) == 2 and player:getStorageValue(Storage.DangerousDepths.Scouts.TimeTaskDiremaws) > 0 then -- Ainda não se passaram as 20h - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "diremaws") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.TimeTaskDiremaws) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) == 2 and player:getStorageValue(Storage.DangerousDepths.Scouts.TimeTaskDiremaws) <= 0 then -- Vai fazer a missão após 20h + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.TimeTaskDiremaws) <= 0 then npcHandler:say({ "The gnomes say that these creatures seem to thrive on mushroom sponges. But not only that, apparently they also lay eggs in their own cadavers to breed even faster. ...", "Yes, disgusting. I guess it provides everything their offspring needs... well, we probably shouldn't go into that much further. Instead we should focus on preventing that from happening. ... ", @@ -108,7 +77,7 @@ local function creatureSayCallback(npc, creature, type, message) }, npc, creature) npcHandler:setTopic(playerId, 2) end - if player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) < 1 then -- Não possuía a missão, agora possui! + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) < 1 then npcHandler:say({ "The gnomes say that these creatures seem to thrive on mushroom sponges. But not only that, apparently they also lay eggs in their own cadavers to breed even faster. ...", "Yes, disgusting. I guess it provides everything their offspring needs... well, we probably shouldn't go into that much further. Instead we should focus on preventing that from happening. ... ", @@ -117,36 +86,34 @@ local function creatureSayCallback(npc, creature, type, message) "Are you willing to help? ", }, npc, creature) npcHandler:setTopic(playerId, 2) - elseif (player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) == 1) and (player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount) < 20) then -- Está na missão porém não terminou a task! - npcHandler:say({ "Come back when you have finished your job." }, npc, creature) + elseif (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) == 1) and (player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount) < 20) then + npcHandler:say("Come back when you have finished your job.", npc, creature) npcHandler:setTopic(playerId, 1) - elseif player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) == 1 and player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount) >= 20 then -- Não possuía a missão, agora possui! - npcHandler:say({ "You got rid of a lot of corpses, very good. Now we have a realistic chance of pushing them back! Return to me later for more work if you want." }, npc, creature) - player:setStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskDiremaws, os.time() + tempo) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount) >= 20 then + npcHandler:say("You got rid of a lot of corpses, very good. Now we have a realistic chance of pushing them back! Return to me later for more work if you want.", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskDiremaws, os.time() + time) player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + 1) - player:setStorageValue(Storage.DangerousDepths.Scouts.Diremaw, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw, 2) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 2 and MsgContains(message, "yes") then - npcHandler:say({ "Noted. Get one of the gnomish devices from the container next to me and 'use' it on any diremaw corpses to effectively neutralise them. At least the gnomes told me this will work - good luck!" }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say("Noted. Get one of the gnomish devices from the container next to me and 'use' it on any diremaw corpses to effectively neutralise them. At least the gnomes told me this will work - good luck!", npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Scouts.Diremaw, 1) - player:setStorageValue(Storage.DangerousDepths.Scouts.GnomishChest, 1) -- Permissão para usar o baú - player:setStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount, 0) -- Garantindo que a task não inicie com -1 - npcHandler:setTopic(playerId, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.GnomishChest, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount, 0) npcHandler:setTopic(playerId, 1) end - -- missão growth - if MsgContains(message, "growth") and npcHandler:getTopic(playerId) == 1 then - if player:getStorageValue(Storage.DangerousDepths.Scouts.Growth) == 2 and player:getStorageValue(Storage.DangerousDepths.Scouts.TimeTaskGrowth) > 0 then -- Ainda não se passaram as 20h - npcHandler:say({ "I don't need your help for now. Come back later." }, npc, creature) + if MsgContains(message, "growth") then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.TimeTaskGrowth) > 0 then + npcHandler:say("I don't need your help for now. Come back later.", npc, creature) npcHandler:setTopic(playerId, 1) end - if player:getStorageValue(Storage.DangerousDepths.Scouts.Growth) == 2 and player:getStorageValue(Storage.DangerousDepths.Scouts.TimeTaskGrowth) <= 0 then -- Vai fazer a missão após 20h + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth) == 2 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.TimeTaskGrowth) <= 0 then npcHandler:say({ "I can't explain that stuff, even the gnomes don't know what grows in those caves. All we know is that this stuff brought about all the diremaws we are now facing. ...", "This vermin is somehow attracted to this sponge, my guess is they use it as a nourishment, too. We need to get rid of the stuff regularly to reduce their numbers to a manageable level. ...", @@ -156,9 +123,8 @@ local function creatureSayCallback(npc, creature, type, message) "We need someone to take those barrels to the source of the ever growing sponge and burn it down. All of it. There should be at least five locations. Are you up for that? ", }, npc, creature) npcHandler:setTopic(playerId, 22) - npcHandler:setTopic(playerId, 22) end - if player:getStorageValue(Storage.DangerousDepths.Scouts.Growth) < 1 then -- Não possuía a missão, agora possui! + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth) < 1 then npcHandler:say({ "I can't explain that stuff, even the gnomes don't know what grows in those caves. All we know is that this stuff brought about all the diremaws we are now facing. ...", "This vermin is somehow attracted to this sponge, my guess is they use it as a nourishment, too. We need to get rid of the stuff regularly to reduce their numbers to a manageable level. ...", @@ -168,109 +134,129 @@ local function creatureSayCallback(npc, creature, type, message) "We need someone to take those barrels to the source of the ever growing sponge and burn it down. All of it. There should be at least five locations. Are you up for that? ", }, npc, creature) npcHandler:setTopic(playerId, 22) - npcHandler:setTopic(playerId, 22) end - if player:getStorageValue(Storage.DangerousDepths.Scouts.Growth) == 1 and player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) >= 3 then -- Não possuía a missão, agora possui! - npcHandler:say({ "You did a great job out there, the stuff will continue to grow, however. Return to me later for more work." }, npc, creature) - player:setStorageValue(Storage.DangerousDepths.Dwarves.TimeTaskGrowth, os.time() + tempo) - if player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) >= 5 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) >= 3 then + npcHandler:say("You did a great job out there, the stuff will continue to grow, however. Return to me later for more work.", npc, creature) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.TimeTaskGrowth, os.time() + time) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) >= 5 then player:addItem(27654, 2) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + 2) else player:addItem(27654, 1) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + 1) end - player:setStorageValue(Storage.DangerousDepths.Scouts.Growth, 2) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth, 2) npcHandler:setTopic(playerId, 1) end elseif npcHandler:getTopic(playerId) == 22 and MsgContains(message, "yes") then - npcHandler:say({ "Noted. Now, get down there and rain some fire on them." }, npc, creature) - if player:getStorageValue(Storage.DangerousDepths.Questline) < 1 then - player:setStorageValue(Storage.DangerousDepths.Questline, 1) + npcHandler:say("Noted. Now, get down there and rain some fire on them.", npc, creature) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Questline, 1) end - player:setStorageValue(Storage.DangerousDepths.Scouts.Growth, 1) - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Scouts.FirstBarrel, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Scouts.SecondBarrel, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Scouts.ThirdBarrel, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Scouts.FourthBarrel, 0) -- Garantindo que a task não inicie com -1 - player:setStorageValue(Storage.DangerousDepths.Scouts.FifthBarrel, 0) -- Garantindo que a task não inicie com -1 + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FirstBarrel, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.SecondBarrel, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.ThirdBarrel, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FourthBarrel, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.FifthBarrel, 0) npcHandler:setTopic(playerId, 1) npcHandler:setTopic(playerId, 1) end + local plural = "" + if MsgContains(message, "suspicious devices") or MsgContains(message, "suspicious device") then - npcHandler:say({ "If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer? " }, npc, creature) + npcHandler:say("If you bring me any suspicious devices on creatures you slay down here, I'll make it worth your while by telling the others of your generosity. How many do you want to offer? ", npc, creature) npcHandler:setTopic(playerId, 55) elseif npcHandler:getTopic(playerId) == 55 then - quantidade[playerId] = tonumber(message) - if quantidade[playerId] then - if quantidade[playerId] > 1 then + amount[playerId] = tonumber(message) + if amount[playerId] then + if amount[playerId] > 1 then plural = plural .. "s" end - npcHandler:say({ "You want to offer " .. quantidade[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) + npcHandler:say("You want to offer " .. amount[playerId] .. " suspicious device" .. plural .. ". Which leader shall have it, (Gnomus) of the {gnomes}, (Klom Stonecutter) of the {dwarves} or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 56) else - npcHandler:say({ "Don't waste my time." }, npc, creature) + npcHandler:say("Don't waste my time.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the gnomes mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the gnomes mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the dwarves mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the dwarves mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 56 then - if player:getItemCount(30888) >= quantidade[playerId] then - npcHandler:say({ "Done." }, npc, creature) - if quantidade[playerId] > 1 then + if player:getItemCount(30888) >= amount[playerId] then + npcHandler:say("Done.", npc, creature) + if amount[playerId] > 1 then plural = plural .. "s" end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. quantidade[playerId] .. " point" .. plural .. " on the scouts mission.") - player:removeItem(30888, quantidade[playerId]) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) + quantidade[playerId]) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You earned " .. amount[playerId] .. " point" .. plural .. " on the scouts mission.") + player:removeItem(30888, amount[playerId]) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + amount[playerId]) else - npcHandler:say({ "You don't have enough suspicious devices." }, npc, creature) + npcHandler:say("You don't have enough suspicious devices.", npc, creature) npcHandler:setTopic(playerId, 1) end end - -- Início checagem de pontos de tasks!! if MsgContains(message, "status") then - npcHandler:say({ "So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?" }, npc, creature) - npcHandler:setTopic(playerId, 5) + npcHandler:say("So you want to know what we all think about your deeds? What leader's opinion are you interested in, the {gnomes} (Gnomus), the {dwarves} (Klom Stonecutter) or the {scouts} (Lardoc Bashsmite)?", npc, creature) npcHandler:setTopic(playerId, 5) elseif MsgContains(message, "gnomes") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Gnomes.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The gnomes are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "dwarves") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Dwarves.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The dwarves are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points), 0) .. "/10)", npc, creature) elseif MsgContains(message, "scouts") and npcHandler:getTopic(playerId) == 5 then - npcHandler:say({ "The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.DangerousDepths.Scouts.Status), 0) .. "/10)" }, npc, creature) + npcHandler:say("The scouts are still in need of your help, member of Bigfoot's Brigade. Prove your worth by answering their calls! (" .. math.max(player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points), 0) .. "/10)", npc, creature) end + return true end +keywordHandler:addKeyword({ "work" }, StdModule.say, { npcHandler = npcHandler, text = "Here's the situation: a tide of hazardous bugs, the gnomes named them {diremaws}, threatens our base. Then there is some kind of {growth} which seems connected to them somehow. We need to get rid of both." }) +keywordHandler:addKeyword({ "worth" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "You're already known amongst the gnomes, member of the Bigfoot Brigade. I will make sure that the alliance learns of your deeds but you'll still need to help the dwarves and gnomes of this outpost to show your worth. ...", + "We also found suspicious devices carried by all kinds of creatures down here. Down here, they are of extreme worth to us since they could contain the key to what's happening all around us. ... ", + "If you can aquire any, return them to me and I make sure to tell the others of your generosity. Return to me afterwards to check on your current {status}.", + }, +}) +keywordHandler:addKeyword({ "job" }, StdModule.say, { + npcHandler = npcHandler, + text = { + "Leading the charge! It's a war down here. I maintain the outer defences and supplies which are organised back in Kazordoon and also by the gnomes. ...", + "I have sealed some of the areas far too dangerous for anyone to enter. If you can prove you're capable, you'll get an oportunity to help destroying the weird machines, pumping lava into the caves leading to the most dangerous enemies.", + "But even if we knew nothing more about them, the fact alone that they employ the help of those mockeries of all things dwarfish, marks them as an enemy of the dwarves and it's our obligation to annihilate them.", + }, +}) +keywordHandler:addKeyword({ "name" }, StdModule.say, { npcHandler = npcHandler, text = "Bashsmite. That's all you need to know." }) + +npcHandler:setMessage(MESSAGE_GREET, "Since you are obviously not one of my relatives who pays me a long overdue visit, we should get {work} right away. We'll see if you can prove your {worth} to our alliance.") npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) diff --git a/data-otservbr-global/npc/maelyrra.lua b/data-otservbr-global/npc/maelyrra.lua index f582f2418c1..2a4bce29fb6 100644 --- a/data-otservbr-global/npc/maelyrra.lua +++ b/data-otservbr-global/npc/maelyrra.lua @@ -61,39 +61,25 @@ local function creatureSayCallback(npc, creature, type, message) if MsgContains(message, "mission") then if player:getStorageValue(ThreatenedDreams.Mission02[1]) < 1 then - npcHandler:say({ - "Some annoying nightmarish creatures rove about in the tunnels underneath this island. They are threatening the members of my court and devastate the flora and fauna. They also threaten the natural balance. Would you go and fight them for me?", - }, npc, creature) + npcHandler:say("Some annoying nightmarish creatures rove about in the tunnels underneath this island. They are threatening the members of my court and devastate the flora and fauna. They also threaten the natural balance. Would you go and fight them for me?", npc, creature) npcHandler:setTopic(playerId, 1) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) >= 1 and player:getStorageValue(ThreatenedDreams.Mission02[1]) <= 2 then - npcHandler:say({ - "Have you defeated the nightmare monsters?", - }, npc, creature) + npcHandler:say("Have you defeated the nightmare monsters?", npc, creature) npcHandler:setTopic(playerId, 2) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) >= 3 and player:getStorageValue(ThreatenedDreams.Mission02[1]) <= 4 then - npcHandler:say({ - "Have you found the moon mirror and freed the captured fairies?", - }, npc, creature) + npcHandler:say("Have you found the moon mirror and freed the captured fairies?", npc, creature) npcHandler:setTopic(playerId, 4) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) == 5 and player:getStorageValue(ThreatenedDreams.Mission03[1]) == 4 then - npcHandler:say({ - "Have you already found the starlight vial and the sun catcher?", - }, npc, creature) + npcHandler:say("Have you already found the starlight vial and the sun catcher?", npc, creature) npcHandler:setTopic(playerId, 6) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) == 6 then - npcHandler:say({ - "Could you already gather the three lights?", - }, npc, creature) + npcHandler:say("Could you already gather the three lights?", npc, creature) npcHandler:setTopic(playerId, 7) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) == 7 then - npcHandler:say({ - "Have you repaired the magical barrier? Is Feyrist safe?", - }, npc, creature) + npcHandler:say("Have you repaired the magical barrier? Is Feyrist safe?", npc, creature) npcHandler:setTopic(playerId, 8) else - npcHandler:say({ - "Thank you again, mortal being! The fae will be forever grateful.", - }, npc, creature) + npcHandler:say("Thank you again, mortal being! The fae will be forever grateful.", npc, creature) npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "yes") then @@ -110,20 +96,14 @@ local function creatureSayCallback(npc, creature, type, message) local frazzlemawsKills = player:getStorageValue(ThreatenedDreams.Mission02.FrazzlemawsCount) local kroazurKill = player:getStorageValue(ThreatenedDreams.Mission02.KroazurKill) if player:getStorageValue(ThreatenedDreams.Mission02[1]) == 1 and kroazurKill >= 1 and (enfeebledKills + frazzlemawsKills) >= 200 then - npcHandler:say({ - "Thank you! You rendered a great favour to the fae courts and Feyrist alike. Would you help us with another problem?", - }, npc, creature) + npcHandler:say("Thank you! You rendered a great favour to the fae courts and Feyrist alike. Would you help us with another problem?", npc, creature) npcHandler:setTopic(playerId, 3) player:setStorageValue(ThreatenedDreams.Mission02[1], 2) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) == 2 then - npcHandler:say({ - "You rendered a great favour to the fae courts and Feyrist alike. Would you help us with another problem?", - }, npc, creature) + npcHandler:say("You rendered a great favour to the fae courts and Feyrist alike. Would you help us with another problem?", npc, creature) npcHandler:setTopic(playerId, 3) else - npcHandler:say({ - "You have to kill two hundred of nightmare creatures and the terrible demon Kroazur who's leading them. That should bring some relief for the fae.", - }, npc, creature) + npcHandler:say("You have to kill two hundred of nightmare creatures and the terrible demon Kroazur who's leading them. That should bring some relief for the fae.", npc, creature) npcHandler:setTopic(playerId, 0) end elseif npcHandler:getTopic(playerId) == 3 then @@ -137,20 +117,14 @@ local function creatureSayCallback(npc, creature, type, message) npcHandler:setTopic(playerId, 0) elseif npcHandler:getTopic(playerId) == 4 then if player:getStorageValue(ThreatenedDreams.Mission02.FairiesCounter) == 5 and player:getStorageValue(ThreatenedDreams.Mission02.DarkMoonMirror) == 1 then - npcHandler:say({ - "Thank you, mortal being! Please keep the mirror. I think you may need it soon, because there is another problem. Would you help us again?", - }, npc, creature) + npcHandler:say("Thank you, mortal being! Please keep the mirror. I think you may need it soon, because there is another problem. Would you help us again?", npc, creature) npcHandler:setTopic(playerId, 5) player:setStorageValue(ThreatenedDreams.Mission02[1], 4) elseif player:getStorageValue(ThreatenedDreams.Mission02[1]) == 4 then - npcHandler:say({ - "Please keep the mirror. I think you may need it soon, because there is another problem. Would you help us again?", - }, npc, creature) + npcHandler:say("Please keep the mirror. I think you may need it soon, because there is another problem. Would you help us again?", npc, creature) npcHandler:setTopic(playerId, 5) else - npcHandler:say({ - "Please seek out the tainted fae, retrieve the artefact and free the captured fairies.", - }, npc, creature) + npcHandler:say("Please seek out the tainted fae, retrieve the artefact and free the captured fairies.", npc, creature) npcHandler:setTopic(playerId, 0) end elseif npcHandler:getTopic(playerId) == 5 then @@ -178,23 +152,17 @@ local function creatureSayCallback(npc, creature, type, message) player:setStorageValue(ThreatenedDreams.Mission02[1], 7) npcHandler:setTopic(playerId, 0) else - npcHandler:say({ - "You have to catch the respective lights and store it in the corresponding vessel.", - }, npc, creature) + npcHandler:say("You have to catch the respective lights and store it in the corresponding vessel.", npc, creature) npcHandler:setTopic(playerId, 0) end elseif npcHandler:getTopic(playerId) == 8 then if player:getStorageValue(ThreatenedDreams.Mission02.ChargedMoonMirror) == 0 and player:getStorageValue(ThreatenedDreams.Mission02.ChargedStarlightVial) == 0 and player:getStorageValue(ThreatenedDreams.Mission02.ChargedSunCatcher) == 0 then - npcHandler:say({ - "Thank you, mortal being! The fae will be forever grateful. Take this blossom bag as a little thank-you gift. Such blossoms grow on our trees just once in a decade, so they are quite rare.", - }, npc, creature) + npcHandler:say("Thank you, mortal being! The fae will be forever grateful. Take this blossom bag as a little thank-you gift. Such blossoms grow on our trees just once in a decade, so they are quite rare.", npc, creature) player:addItem(25780, 1) player:setStorageValue(ThreatenedDreams.Mission02[1], 8) npcHandler:setTopic(playerId, 0) else - npcHandler:say({ - "If you charge all fifteen arcane sources with the respective light, Feyrist's protection will be ensured again.", - }, npc, creature) + npcHandler:say("If you charge all fifteen arcane sources with the respective light, Feyrist's protection will be ensured again.", npc, creature) npcHandler:setTopic(playerId, 0) end end diff --git a/data-otservbr-global/npc/muriel.lua b/data-otservbr-global/npc/muriel.lua index 8017528a681..8aece06cd9a 100644 --- a/data-otservbr-global/npc/muriel.lua +++ b/data-otservbr-global/npc/muriel.lua @@ -76,19 +76,58 @@ local function creatureSayCallback(npc, creature, type, message) "The rotworms dug deep into the soil north of Thais. Rumours say that you can access a place of endless moaning from there. ...", "No one knows how old that common grave is but the people who died there are cursed and never come to rest. A bone from that pit would be perfect for my studies.", }, npc, creature) + npcHandler:setTopic(playerId, 0) elseif player:getStorageValue(Storage.Quest.U8_1.TibiaTales.IntoTheBonePit) == 2 then player:setStorageValue(Storage.Quest.U8_1.TibiaTales.IntoTheBonePit, 3) if player:removeItem(131, 1) then player:addItem(6299, 1) npcHandler:say("Excellent! Now I can try to put my theoretical thoughts into practice and find a cure for the symptoms of undead. Here, take this for your efforts.", npc, creature) + npcHandler:setTopic(playerId, 0) else npcHandler:say({ "I am so glad you are still alive. Benjamin found the container with the bone sample inside. Fortunately, I inscribe everything with my name, so he knew it was mine. ...", "I thought you have been haunted and killed by the undead. I'm glad that this is not the case. Thank you for your help.", }, npc, creature) + npcHandler:setTopic(playerId, 0) end else npcHandler:say("I am very glad you helped me, but I am very busy at the moment.", npc, creature) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "addons") then + local hasMasks = player:getItemCount(25088) >= 3 + local hasFeathers = player:getItemCount(25089) >= 50 + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) == 2 and player:getStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon1) == 1 and hasMasks then + npcHandler:say("I see you have the porcelain masks. Are you ready to exchange them for the first addon?", npc, creature) + npcHandler:setTopic(playerId, 2) + elseif player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) == 2 and player:getStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon2) == 1 and hasFeathers then + npcHandler:say("I see you have the colourful feathers. Are you ready to exchange them for the second addon?", npc, creature) + npcHandler:setTopic(playerId, 4) + else + npcHandler:say("You need the outfit and 3 porcelain masks or 50 colored feathers to get the festive costume accessories.", npc, creature) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "mask") and player:getStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon1) == 1 then + if player:removeItem(25088, 3) then + player:addOutfit(929, 1) + player:addOutfit(931, 1) + npcHandler:say("Very good! You gained the first addon to the festive outfit.", npc, creature) + player:setStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon1, 2) + npcHandler:setTopic(playerId, 0) + else + npcHandler:say("Oh, sorry but you don't have enough porcelain masks!", npc, creature) + npcHandler:setTopic(playerId, 0) + end + elseif MsgContains(message, "feather") and player:getStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon2) == 1 then + if player:removeItem(25089, 50) then + player:addOutfit(929, 2) + player:addOutfit(931, 2) + npcHandler:say("Very good! You gained the second addon to the festive outfit.", npc, creature) + player:setStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon2, 2) + npcHandler:setTopic(playerId, 0) + else + npcHandler:say("Oh, sorry but you don't have enough colourful feathers!", npc, creature) + npcHandler:setTopic(playerId, 0) end elseif MsgContains(message, "yes") then if npcHandler:getTopic(playerId) == 1 then @@ -98,12 +137,22 @@ local function creatureSayCallback(npc, creature, type, message) }, npc, creature) player:addItem(4852, 1) player:setStorageValue(Storage.Quest.U8_1.TibiaTales.IntoTheBonePit, 1) + npcHandler:setTopic(playerId, 0) + elseif npcHandler:getTopic(playerId) == 2 then + npcHandler:say("I provide two addons. For the first one I need you to bring me three porcelain masks. For the second addon you need fifty colourful ostrich feathers. Do you want one of these addons?", npc, creature) + npcHandler:setTopic(playerId, 3) + elseif npcHandler:getTopic(playerId) == 3 then + npcHandler:say("What do you have for me: the porcelain masks or the colourful feathers?", npc, creature) + player:setStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon1, 1) + elseif npcHandler:getTopic(playerId) == 4 then + npcHandler:say("I provide two addons. For the first one I need you to bring me three porcelain masks. For the second addon you need fifty colourful ostrich feathers. Do you want one of these addons?", npc, creature) + player:setStorageValue(Storage.Quest.U11_02.FestiveOutfits.Addon2, 1) end elseif MsgContains(message, "no") then - if npcHandler:getTopic(playerId) == 1 then - npcHandler:say("Ohh, then I need to find another adventurer who wants to earn a great reward. Bye!", npc, creature) - end + npcHandler:say("Ohh, then I need to find another adventurer who wants to earn a great reward. Bye!", npc, creature) + npcHandler:setTopic(playerId, 0) end + return true end diff --git a/data-otservbr-global/npc/nomad.lua b/data-otservbr-global/npc/nomad.lua index 79dee9cc229..2e33e91a872 100644 --- a/data-otservbr-global/npc/nomad.lua +++ b/data-otservbr-global/npc/nomad.lua @@ -50,8 +50,8 @@ npcType.onCloseChannel = function(npc, creature) end -- Heart of the Mountain -local blessKeyword = keywordHandler:addKeyword({ "heart" }, StdModule.say, { npcHandler = npcHandler, text = "Would you like to receive that protection for a sacrifice of |BLESSCOST| gold, child?" }) -blessKeyword:addChildKeyword({ "yes" }, StdModule.bless, { npcHandler = npcHandler, text = "So receive the Heart of the Mountain, pilgrim.", cost = "|BLESSCOST|", bless = 8 }) +local blessKeyword = keywordHandler:addKeyword({ "enhanced" }, StdModule.say, { npcHandler = npcHandler, text = "I am able to grant you the heart of the mountain's blessing. But I must ask of you to sacrifice |BLESSCOST| gold. Are you willing to part with that amount of wealth?" }) +blessKeyword:addChildKeyword({ "yes" }, StdModule.bless, { npcHandler = npcHandler, text = "Receive the heart of the mountain then.", cost = "|BLESSCOST|", bless = 7 }) blessKeyword:addChildKeyword({ "" }, StdModule.say, { npcHandler = npcHandler, text = "Fine. You are free to decline my offer.", reset = true }) -- Healing @@ -62,6 +62,7 @@ local function addHealKeyword(text, condition, effect) player:removeCondition(condition) player:getPosition():sendMagicEffect(effect) end) + keywordHandler:addAliasKeyword({ "help" }) end addHealKeyword("You are burning. Let me quench those flames.", CONDITION_FIRE, CONST_ME_MAGIC_GREEN) @@ -78,26 +79,17 @@ end, function(player) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) end) keywordHandler:addKeyword({ "heal" }, StdModule.say, { npcHandler = npcHandler, text = "You aren't looking that bad. Sorry, I can't help you. But if you are looking for additional protection you should go on the {pilgrimage} of ashes or get the protection of the {twist of fate} here." }) +keywordHandler:addAliasKeyword({ "help" }) -- Basic -keywordHandler:addKeyword({ "pilgrimage" }, StdModule.say, { npcHandler = npcHandler, text = "Whenever you receive a lethal wound, your vital force is damaged and there is a chance that you lose some of your equipment. With every single of the five {blessings} you have, this damage and chance of loss will be reduced." }) -keywordHandler:addKeyword({ "blessings" }, StdModule.say, { npcHandler = npcHandler, text = "There are five blessings available in five sacred places: the {spiritual} shielding, the spark of the {phoenix}, the {embrace} of Tibia, the fire of the {suns} and the wisdom of {solitude}. Additionally, you can receive the {twist of fate} here." }) -keywordHandler:addKeyword({ "spiritual" }, StdModule.say, { npcHandler = npcHandler, text = "I see you received the spiritual shielding in the whiteflower temple south of Thais." }, function(player) - return player:hasBlessing(1) -end) -keywordHandler:addAliasKeyword({ "shield" }) -keywordHandler:addKeyword({ "suns" }, StdModule.say, { npcHandler = npcHandler, text = "I can see you received the blessing of the two suns in the suntower near Ab'Dendriel." }, function(player) - return player:hasBlessing(3) -end) -keywordHandler:addAliasKeyword({ "fire" }) -keywordHandler:addKeyword({ "phoenix" }, StdModule.say, { npcHandler = npcHandler, text = "I can sense that the spark of the phoenix already was given to you by the dwarven priests of earth and fire in Kazordoon." }, function(player) - return player:hasBlessing(4) -end) -keywordHandler:addAliasKeyword({ "spark" }) -keywordHandler:addKeyword({ "solitude" }, StdModule.say, { npcHandler = npcHandler, text = "I can sense you already talked to the hermit Eremo on the isle of Cormaya and received this blessing." }, function(player) - return player:hasBlessing(5) -end) -keywordHandler:addAliasKeyword({ "wisdom" }) +keywordHandler:addKeyword({ "blessing" }, StdModule.say, { + npcHandler = npcHandler, + text = "Besides the {enhanced} blessing available from me, I know of one other, granted by a solitary {nomad} far west of Svargrond. There are also five different other blessings available, each in a sacred place. ...\nThese blessings are: the {spiritual} shielding, the spark of the {phoenix}, the {embrace} of Tibia, the fire of the {suns} and the wisdom of {solitude}.", +}) + +keywordHandler:addKeyword({ "pilgrimage" }, StdModule.say, { npcHandler = npcHandler, text = "Well, as I am quite in a {fix} currently, my only hope to escape this situation may be to grant you {healing} or an {enhanced} blessing if you wish. You must desire SOMETHING, right? Sure you do." }) +keywordHandler:addAliasKeyword({ "job" }) + keywordHandler:addKeyword({ "spiritual" }, StdModule.say, { npcHandler = npcHandler, text = "You can ask for the blessing of spiritual shielding in the whiteflower temple south of Thais." }) keywordHandler:addAliasKeyword({ "shield" }) keywordHandler:addKeyword({ "suns" }, StdModule.say, { npcHandler = npcHandler, text = "You can ask for the blessing of the two suns in the suntower near Ab'Dendriel." }) @@ -106,10 +98,16 @@ keywordHandler:addKeyword({ "phoenix" }, StdModule.say, { npcHandler = npcHandle keywordHandler:addAliasKeyword({ "spark" }) keywordHandler:addKeyword({ "solitude" }, StdModule.say, { npcHandler = npcHandler, text = "Talk to the hermit Eremo on the isle of Cormaya about this blessing." }) keywordHandler:addAliasKeyword({ "wisdom" }) +keywordHandler:addKeyword({ "embrace" }, StdModule.say, { npcHandler = npcHandler, text = "The druids north of Carlin will provide you with the embrace of Tibia." }) +keywordHandler:addAliasKeyword({ "tibia" }) + +keywordHandler:addKeyword({ "djinn" }, StdModule.say, { npcHandler = npcHandler, text = "I know of a mysterious djinn, bound to an existence of slavery far to the north of Tiquanda's jungles. He is bound to tell you his secrets and offer you the 'blood of the mountain'. ...\nI do not know where exactly but I guess you must first dig that one out to actually talk to him." }) +keywordHandler:addKeyword({ "nomad" }, StdModule.say, { npcHandler = npcHandler, text = "I am one with nature, one with the ice and the cold. Names are of no worth out here. Out here, you face isolation and loneliness. Only your strength, willpower and {training} can keep you alive." }) +keywordHandler:addKeyword({ "training" }, StdModule.say, { npcHandler = npcHandler, text = "My life is one of hardship, hardship I chose freely. Endurance, strength and the power of the will are my only companions in this frigid wilderness. My strength comes from disciplined training and knowledge of the outdoors." }) -npcHandler:setMessage(MESSAGE_GREET, "Welcome, noble |PLAYERNAME|") -npcHandler:setMessage(MESSAGE_WALKAWAY, "Good Bye, noble |PLAYERNAME|") -npcHandler:setMessage(MESSAGE_FAREWELL, "Good Bye, noble |PLAYERNAME|") +npcHandler:setMessage(MESSAGE_GREET, "Ah, another diciple of the extreme... surviving the icy outdoors? Let me {help}! If you need some first aid out here, I can provide {healing} or grant you an {enhanced} blessing!") +npcHandler:setMessage(MESSAGE_WALKAWAY, "Keep a stiff upper lip!") +npcHandler:setMessage(MESSAGE_FAREWELL, "Keep a stiff upper lip!") npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/noozer.lua b/data-otservbr-global/npc/noozer.lua index 855e3e0174b..5a0478fa2f3 100644 --- a/data-otservbr-global/npc/noozer.lua +++ b/data-otservbr-global/npc/noozer.lua @@ -50,15 +50,6 @@ npcType.onCloseChannel = function(npc, creature) npcHandler:onCloseChannel(npc, creature) end -local function greetCallback(npc, creature) - local playerId = creature:getId() - local player = Player(creature) - - npcHandler:setMessage(MESSAGE_GREET, "Hm? Oh! Oh, yes a... visitor! Intruder? Benefactor...? Wha- what are you? If you want to {pass} through this {cave}, I may have to disappoint you. Or maybe not. It... depends. So, just passing through?.") - npcHandler:setTopic(playerId, 1) - - return true -end local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -67,8 +58,7 @@ local function creatureSayCallback(npc, creature, type, message) return false end - -- Começou a quest - if MsgContains(message, "pass") and npcHandler:getTopic(playerId) == 1 then + if MsgContains(message, "pass") then npcHandler:say({ "Yes, yes. Or wait - why do you want to.. ah what does it matter. So you want to get through these {caves}, fine. But be warned! ...", "...wait a second, I lost it. What was I going to say again? Ah yes - DANGEROUS! These. Caves. Are. Dangerous. No way you get out alive. Ever. Again. ...", @@ -76,29 +66,31 @@ local function creatureSayCallback(npc, creature, type, message) "Wait - I am the guardian here, yes! The keeper of... something... or another, yes, I... guard this place. With my life. Don't I? Of course! ...", "Is, er... this the moment where I should try to... stop you? Yes? No? Ah, you know what - you go down there, those guys are angry as dung anyway. Try your luck, return to me when you're done. If you still can. Or not.", }, npc, creature) - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) - end - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) < 2 then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Mission, 2) - player:setStorageValue(Storage.CultsOfTibia.Misguided.AccessDoor, 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) < 2 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, 2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.AccessDoor, 1) end - elseif MsgContains(message, "cave") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ "I was stationed in this cave to... guard something. Right now I am not even sure what that was." }, npc, creature) - elseif MsgContains(message, "job") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ "Then don't waste my time. I'm doing some important... business... here. Actually... where am I? If I find out, I will be even more angry than I am now. Out of my sight." }, npc, creature) - elseif MsgContains(message, "mission") and npcHandler:getTopic(playerId) == 1 then - npcHandler:say({ "I was on a mission, too - I guess. It was all quite blurry back then. Maybe I'll leave this place after I recovered completely. I have to find out what happened to me." }, npc, creature) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "cave") then + npcHandler:say("I was stationed in this cave to... guard something. Right now I am not even sure what that was.", npc, creature) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "job") then + npcHandler:say("Then don't waste my time. I'm doing some important... business... here. Actually... where am I? If I find out, I will be even more angry than I am now. Out of my sight.", npc, creature) + npcHandler:setTopic(playerId, 0) + elseif MsgContains(message, "mission") then + npcHandler:say("I was on a mission, too - I guess. It was all quite blurry back then. Maybe I'll leave this place after I recovered completely. I have to find out what happened to me.", npc, creature) + npcHandler:setTopic(playerId, 0) end + return true end +npcHandler:setMessage(MESSAGE_GREET, "Hm? Oh! Oh, yes a... visitor! Intruder? Benefactor...? Wha- what are you? If you want to pass through this cave, I may have to disappoint you. Or maybe not. It... depends. So, just passing through?") npcHandler:setMessage(MESSAGE_WALKAWAY, "Well, bye then.") npcHandler:setCallback(CALLBACK_SET_INTERACTION, onAddFocus) npcHandler:setCallback(CALLBACK_REMOVE_INTERACTION, onReleaseFocus) -npcHandler:setCallback(CALLBACK_GREET, greetCallback) npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) diff --git a/data-otservbr-global/npc/spectulus.lua b/data-otservbr-global/npc/spectulus.lua index 9856bce82c0..6bed2acf958 100644 --- a/data-otservbr-global/npc/spectulus.lua +++ b/data-otservbr-global/npc/spectulus.lua @@ -424,13 +424,39 @@ local function creatureSayCallback(npc, creature, type, message) "Are you willing to help me?", }, npc, creature) npcHandler:setTopic(playerId, 25) - elseif MsgContains(message, "yes") and npcHandler:getTopic(playerId) == 25 then + elseif MsgContains(message, "yes") then if npcHandler:getTopic(playerId) == 25 then npcHandler:say("Excellent, excellent. The rumours pointed to the north of Tiquanda, a sunken temple probably half drowned in water. Return to me if you find anything interesting!", npc, creature) - player:setStorageValue(Storage.TheSecretLibrary.LiquidDeath, 1) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, 1) + end npcHandler:setTopic(playerId, 0) end end + + if MsgContains(message, "njey") then + npcHandler:say({ + "Mh? Ah, yes yes. 'Njey' is the native-language term for a very old race of undersea creatures which ...", + "...hm, wait - only a select few of my colleagues even bothered studying their culture. They are a mere fantasy to the common man - is there anything of importance you want to tell me?", + }, npc, creature) + npcHandler:setTopic(playerId, 26) + elseif MsgContains(message, "yes") then + if npcHandler:getTopic(playerId) == 26 then + npcHandler:say({ + "Well, if you really want to delve into this - I could use some help. So you have found my machine on that island? And you found the notes with the coordinates? Then you can find the entrance! ...", + "Just look for a large staircase with sprawling steps. There is an unpassable stream there that will prevent you from venturing further on. But fear not, you can indeed travel down there - with these small enhancements I created. ...", + "I will put this under your footgear. Here you go. And this in your nose. There. And there will be no further problems for you down there. Except- ah, well you'll find out yourself soon enough, won't you?", + }, npc, creature) + npcHandler:setTopic(playerId, 34) + elseif npcHandler:getTopic(playerId) == 34 then + npcHandler:say("Then off you go! I'm sorry that I cannot offer you any further help but I'm sure you will find support along your way. And - be careful. The sea can appear pitch black down there.", npc, creature) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) < 4 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, 4) + end + npcHandler:setTopic(playerId, 0) + end + end + return true end diff --git a/data-otservbr-global/npc/tamoril.lua b/data-otservbr-global/npc/tamoril.lua index 654355d9be5..e6ed393420f 100644 --- a/data-otservbr-global/npc/tamoril.lua +++ b/data-otservbr-global/npc/tamoril.lua @@ -42,16 +42,26 @@ npcType.onThink = function(npc, interval) npcHandler:onThink(npc, interval) end -local function greetCallback(npc, creature) - local playerId = creature:getId() - npcHandler:setMessage(MESSAGE_GREET, "Another pesky mortal who believes his gold outweighs his nutrition value.") - return true +local function isDateWithinEvent() + local currentDate = os.date("*t") + local startDate = { day = 14, month = 1 } + local endDate = { day = 12, month = 2 } + + if (currentDate.month == startDate.month and currentDate.day >= startDate.day) or (currentDate.month == endDate.month and currentDate.day <= endDate.day) or (currentDate.month > startDate.month and currentDate.month < endDate.month) then + return true + end + return false end local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() + if not isDateWithinEvent() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only discuss the First Dragon between January 14 and February 12.") + return true + end + if MsgContains(message, "first dragon") then npcHandler:say("The First Dragon? The first of all of us? The Son of Garsharak? I'm surprised you heard about him. It is such a long time that he wandered Tibia. Yet, there are some {rumours}.", npc, creature) npcHandler:setTopic(playerId, 1) @@ -86,15 +96,22 @@ local function creatureSayCallback(npc, creature, type, message) "And finally an amethyst teleporter in undead-infested caverns underneath Edron allows you to enter the lair of Zorvorax.", }, npc, creature) npcHandler:setTopic(playerId, 0) - player:setStorageValue(Storage.FirstDragon.Questline, 1) - player:setStorageValue(Storage.FirstDragon.DragonCounter, 0) - player:setStorageValue(Storage.FirstDragon.ChestCounter, 0) - player:setStorageValue(Storage.FirstDragon.GelidrazahAccess, 0) - player:setStorageValue(Storage.FirstDragon.SecretsCounter, 0) + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.Questline, 1) + end + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter) < 0 then + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter, 0) + end + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.DragonCounter, 0) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.GelidrazahAccess, 0) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.SecretsCounter, 0) end + return true end -npcHandler:setCallback(CALLBACK_GREET, greetCallback) + +npcHandler:setMessage(MESSAGE_GREET, "Another pesky mortal who believes his gold outweighs his nutrition value.") + npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new(), npcConfig.name, true, true, true) @@ -107,6 +124,7 @@ npcConfig.shop = { { itemName = "white gem", clientId = 32769, sell = 12000 }, { itemName = "yellow gem", clientId = 3037, sell = 1000 }, } + -- On buy npc shop message npcType.onBuyItem = function(npc, player, itemId, subType, amount, ignore, inBackpacks, totalCost) npc:sellItem(player, itemId, amount, subType, 0, ignore, inBackpacks) diff --git a/data-otservbr-global/npc/the_first_dragon.lua b/data-otservbr-global/npc/the_first_dragon.lua index 64b10bc4cf5..ec3ba95d004 100644 --- a/data-otservbr-global/npc/the_first_dragon.lua +++ b/data-otservbr-global/npc/the_first_dragon.lua @@ -54,28 +54,30 @@ local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() - if MsgContains(message, "reward") and npcHandler:getTopic(playerId) == 0 and player:getStorageValue(34013) < 1 then + if MsgContains(message, "reward") and player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) == 1 then npcHandler:say({ "Have a look at the chests over there. Feel free to take the things you find within. You know, gold, gems and the like. There's also a garment I'm storing here for a while. As it doesn't fit me I have no need for it. ...", "But it might be a nice outfit for a little human. You also can take the porcelain mask and the feathers. There's a wizard named Muriel in Thais who reportedly embellishes outfits with stuff like this.", }, npc, creature) - player:addOutfit(929, 1) - player:addOutfit(931, 1) + player:addOutfit(929, 0) + player:addOutfit(931, 0) player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) - player:setStorageValue(34013, 1) + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) < 2 then + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers, 2) + end npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "fight") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "fight") then npcHandler:say({ "Even in {retirement} I sometimes succumb to the temptation of sweet battle. Fighting was so different back in the old {times}. You can read about it in my {memoirs}. There should be a copy lying here somewhere.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "retirement") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "retirement") then npcHandler:say({ "When you are young, you are much more tolerant towards the burden of life. At a certain age even a {dragon} will start to think about if things will go on forever. ...", "Eventually there comes a time when you decide all the {hassle} isn't worth it anymore and you decide to concentrate on the {finer} things life has to offer.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "memoirs") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "memoirs") then npcHandler:say({ "I dictated my memoirs to a human servant. I like the idea to share my thoughts and memories with humanity with the help of a {book}. ...", "You are my greatest fans after all. ...", @@ -83,37 +85,37 @@ local function creatureSayCallback(npc, creature, type, message) "By the way, it's a funny story how I learnt the bonelord language. However, I saved it for a possible part two of my memoirs.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "hassle") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "hassle") then npcHandler:say({ "I really enjoy a good fight now and then. ...", "A real pain, however, is the constant annoyance caused by tedious fights against adventurers with more healing pots than brain.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "worthy") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "worthy") then npcHandler:say({ "To be honest, the first dragon hunters weren't {worthy}. ...", "They used {weaknesses} to their advantage. It took some time before a dragon could be killed in a fair fight.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "weaknesses") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "weaknesses") then npcHandler:say({ "The first awoken dragons were quite disoriented when leaving the {mists} and re-entering reality. ...", "This led to certain vulnerabilities. However, the dragons overcame such shortcomings quickly and soon took their rightful place in the food chain, so to say.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "mists") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "mists") then npcHandler:say({ "There was a time before the gods cast the mists of healing over the world. At that time the dragons ruled and burnt the {world}. ...", "In hindsight I'm not too proud of this. This was some kind of juvenile bullying.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "world") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "world") then npcHandler:say({ "The world has changed so much; I'm beginning to feel really old. People have changed, the face of the world has changed, even the laws of nature are no longer the same. ...", "I think it is the greatest advantage of you {humans} to be more flexible and adaptable.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "books") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "books") then npcHandler:say({ "Your books are an amazing thing. Draconic glyphs are so different. ...", "They are not only more complicated but also more specific. A single word which always keeps the same meaning is astonishingly effective in its primitive way. ...", @@ -121,19 +123,19 @@ local function creatureSayCallback(npc, creature, type, message) "Books are a wonderful {invention}. If you are ever tired of your heroic exploits, take the time to read one.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "invention") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "invention") then npcHandler:say({ "Being powerful creatures themselves, dragons had no need for inventions. ...", "However, now that times have changed and the pressure increases, even my kin might slowly start to change in order to {adapt}.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "adapt") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "adapt") then npcHandler:say({ "Well, surely some of my kin might whine and complain as they always do. ...", "You have no idea how backwards thinking some dragons can be. A few are even still idealising the times before the {mists}.", }, npc, creature) npcHandler:setTopic(playerId, 0) - elseif MsgContains(message, "finer") and npcHandler:getTopic(playerId) == 0 then + elseif MsgContains(message, "finer") then npcHandler:say({ "The definition of finer things is different for a dragon than for a human. ...", "A young dragon appreciates diving into a lava pool, while an old dragon just can't stand to get rid of the {lava} afterwards and prefers bathing in boiling water.", @@ -144,6 +146,8 @@ local function creatureSayCallback(npc, creature, type, message) return true end +npcHandler:setMessage(MESSAGE_GREET, "Hello, my sparring buddy. We should have another fight sometimes. I think you may have earned a little reward.") + keywordHandler:addKeyword({ "times" }, StdModule.say, { npcHandler = npcHandler, text = "Times have changed . In the past dragons were feared and respected. Only the {demons} rivalled our notoriety." }) keywordHandler:addKeyword({ "demons" }, StdModule.say, { npcHandler = npcHandler, text = "Those upstarts! I wonder why would anyone care about them. They lack our style. For them it is all about brute force and showing-off." }) keywordHandler:addKeyword({ "style" }, StdModule.say, { npcHandler = npcHandler, text = "Breathing fire is an art! Instead of setting everything on fire, you exhale a cone of fire to give a worthy opponent a chance to avoid it." }) diff --git a/data-otservbr-global/npc/tigo.lua b/data-otservbr-global/npc/tigo.lua index 70646d20e40..c663f6ff812 100644 --- a/data-otservbr-global/npc/tigo.lua +++ b/data-otservbr-global/npc/tigo.lua @@ -55,12 +55,14 @@ local function greetCallback(npc, creature) local player = Player(creature) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Mission) < 2 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission) < 2 then npcHandler:setMessage(MESSAGE_GREET, "There, there initiate. You will now become one of us, as so many before you. One of the {Barkless}. Walk with us and you will walk tall my friend.") npcHandler:setTopic(playerId, 1) end + return true end + local function creatureSayCallback(npc, creature, type, message) local player = Player(creature) local playerId = player:getId() @@ -69,23 +71,13 @@ local function creatureSayCallback(npc, creature, type, message) return false end - -- Começou a quest - if MsgContains(message, "barkless") and npcHandler:getTopic(playerId) == 1 then + if MsgContains(message, "barkless") and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission) == 1 then npcHandler:say({ "You are now one of us. Learn to endure this world's suffering in every facet and take delight in the soothing eternity that waits for the {purest} of us on the other side." }, npc, creature) - npcHandler:setTopic(playerId, 2) - npcHandler:setTopic(playerId, 2) - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) - end - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Mission) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 1) - player:setStorageValue(Storage.CultsOfTibia.Barkless.TrialAccessDoor, 1) - end - elseif MsgContains(message, "purest") and npcHandler:getTopic(playerId) == 2 then + npcHandler:setTopic(playerId, 1) + elseif MsgContains(message, "purest") and npcHandler:getTopic(playerId) == 1 then npcHandler:say({ "Purification is but one of the difficult steps on your way to the other side. The {trial} of tar, sulphur and ice." }, npc, creature) npcHandler:setTopic(playerId, 2) - npcHandler:setTopic(playerId, 2) - elseif MsgContains(message, "trial") and npcHandler:getTopic(playerId) == 3 then + elseif MsgContains(message, "trial") and npcHandler:getTopic(playerId) == 2 then npcHandler:say({ "The trial consists of three steps. The trial of tar, where you will suffer unbearable heat and embrace the stigma of misfortune. ...", "The trial of sulphur, where you will bathe in burning sulphur and embrace the stigma of vanity. Then, there is the trial of purification. The truest of us will be purified to face judgement from the {Penitent}.", @@ -94,9 +86,10 @@ local function creatureSayCallback(npc, creature, type, message) "If he does, follow him into his own chambers. Barkless are neither allowed to go near the throne room, aside from being judged, nor can we actually enter it.", "He should be easy to defeat with his back to the wall, find him - and delvier us from whatever became of the Penitent.", }, npc, creature) - npcHandler:setTopic(playerId, 0) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.TrialAccessDoor, 1) npcHandler:setTopic(playerId, 0) end + return true end diff --git a/data-otservbr-global/scripts/actions/bosses_levers/brokul.lua b/data-otservbr-global/scripts/actions/bosses_levers/brokul.lua deleted file mode 100644 index 2cdded463af..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/brokul.lua +++ /dev/null @@ -1,23 +0,0 @@ -local config = { - boss = { - name = "Brokul", - position = Position(33483, 31434, 15), - }, - requiredLevel = 150, - playerPositions = { - { pos = Position(33522, 31465, 15), teleport = Position(33483, 31445, 15), effect = CONST_ME_TELEPORT }, - { pos = Position(33520, 31465, 15), teleport = Position(33483, 31445, 15), effect = CONST_ME_TELEPORT }, - { pos = Position(33521, 31465, 15), teleport = Position(33483, 31445, 15), effect = CONST_ME_TELEPORT }, - { pos = Position(33523, 31465, 15), teleport = Position(33483, 31445, 15), effect = CONST_ME_TELEPORT }, - { pos = Position(33524, 31465, 15), teleport = Position(33483, 31445, 15), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33469, 31430, 15), - to = Position(33497, 31453, 15), - }, - exit = Position(33522, 31468, 15), -} - -local lever = BossLever(config) -lever:aid(34000) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/dragonking_zyrtarch.lua b/data-otservbr-global/scripts/actions/bosses_levers/dragonking_zyrtarch.lua deleted file mode 100644 index 99585188b91..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/dragonking_zyrtarch.lua +++ /dev/null @@ -1,30 +0,0 @@ -local config = { - boss = { - name = "soul of dragonking zyrtarch", - position = Position(33359, 31182, 12), - }, - requiredLevel = 250, - playerPositions = { - { pos = Position(33391, 31178, 10), teleport = Position(33359, 31186, 10) }, - { pos = Position(33391, 31179, 10), teleport = Position(33359, 31186, 10) }, - { pos = Position(33391, 31180, 10), teleport = Position(33359, 31186, 10) }, - { pos = Position(33391, 31181, 10), teleport = Position(33359, 31186, 10) }, - { pos = Position(33391, 31182, 10), teleport = Position(33359, 31186, 10) }, - }, - monsters = { - { name = "soulcatcher", pos = Position(33352, 31187, 10) }, - { name = "soulcatcher", pos = Position(33363, 31187, 10) }, - { name = "soulcatcher", pos = Position(33353, 31176, 10) }, - { name = "soulcatcher", pos = Position(33363, 31176, 10) }, - { name = "dragonking zyrtarch", pos = Position(33357, 31182, 10) }, - }, - specPos = { - from = Position(33348, 31172, 10), - to = Position(33368, 31190, 12), - }, - exit = Position(33407, 31172, 10), -} - -local lever = BossLever(config) -lever:position(Position(33391, 31177, 10)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/lady_tenebris.lua b/data-otservbr-global/scripts/actions/bosses_levers/lady_tenebris.lua deleted file mode 100644 index 795b3cf2234..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/lady_tenebris.lua +++ /dev/null @@ -1,28 +0,0 @@ -local config = { - boss = { - name = "Lady Tenebris", - position = Position(32912, 31599, 14), - }, - requiredLevel = 250, - playerPositions = { - { pos = Position(32902, 31623, 14), teleport = Position(32911, 31603, 14) }, - { pos = Position(32902, 31624, 14), teleport = Position(32911, 31603, 14) }, - { pos = Position(32902, 31625, 14), teleport = Position(32911, 31603, 14) }, - { pos = Position(32902, 31626, 14), teleport = Position(32911, 31603, 14) }, - { pos = Position(32902, 31627, 14), teleport = Position(32911, 31603, 14) }, - }, - monsters = { - { name = "shadow tentacle", pos = Position(32910, 31599, 14) }, - { name = "shadow tentacle", pos = Position(32912, 31597, 14) }, - { name = "shadow tentacle", pos = Position(32914, 31599, 14) }, - }, - specPos = { - from = Position(32899, 31587, 14), - to = Position(32923, 31612, 14), - }, - exit = Position(32902, 31629, 14), -} - -local lever = BossLever(config) -lever:position(Position(32902, 31622, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/lloyd.lua b/data-otservbr-global/scripts/actions/bosses_levers/lloyd.lua deleted file mode 100644 index 7a2fa1d0a86..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/lloyd.lua +++ /dev/null @@ -1,29 +0,0 @@ -local config = { - boss = { - name = "Lloyd", - position = Position(32799, 32827, 14), - }, - requiredLevel = 250, - playerPositions = { - { pos = Position(32759, 32868, 14), teleport = Position(32800, 32831, 14) }, - { pos = Position(32759, 32869, 14), teleport = Position(32800, 32831, 14) }, - { pos = Position(32759, 32870, 14), teleport = Position(32800, 32831, 14) }, - { pos = Position(32759, 32871, 14), teleport = Position(32800, 32831, 14) }, - { pos = Position(32759, 32872, 14), teleport = Position(32800, 32831, 14) }, - }, - monsters = { - { name = "cosmic energy prism a invu", pos = Position(32801, 32827, 14) }, - { name = "cosmic energy prism b invu", pos = Position(32798, 32827, 14) }, - { name = "cosmic energy prism c invu", pos = Position(32803, 32826, 14) }, - { name = "cosmic energy prism d invu", pos = Position(32796, 32826, 14) }, - }, - specPos = { - from = Position(32785, 32813, 14), - to = Position(32812, 32838, 14), - }, - exit = Position(32815, 32873, 13), -} - -local lever = BossLever(config) -lever:position(Position(32759, 32867, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/melting_frozen_horror.lua b/data-otservbr-global/scripts/actions/bosses_levers/melting_frozen_horror.lua deleted file mode 100644 index fbb60e8fec2..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/melting_frozen_horror.lua +++ /dev/null @@ -1,34 +0,0 @@ -local eggPos = Position(32269, 31084, 14) -local config = { - boss = { - name = "Melting Frozen Horror", - createFunction = function() - Tile(eggPos):getTopCreature():setHealth(1) - return Game.createMonster("solid frozen horror", Position(32269, 31091, 14), true, true) - end, - }, - timeToDefeat = 15 * 60, -- In seconds - requiredLevel = 250, - playerPositions = { - { pos = Position(32302, 31088, 14), teleport = Position(32271, 31097, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32302, 31089, 14), teleport = Position(32271, 31097, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32302, 31090, 14), teleport = Position(32271, 31097, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32302, 31091, 14), teleport = Position(32271, 31097, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32302, 31092, 14), teleport = Position(32271, 31097, 14), effect = CONST_ME_TELEPORT }, - }, - monsters = { - { name = "icicle", pos = Position(32266, 31084, 14) }, - { name = "icicle", pos = Position(32272, 31084, 14) }, - { name = "dragon egg", pos = eggPos }, - { name = "melting frozen horror", pos = Position(32267, 31071, 14) }, - }, - specPos = { - from = Position(32257, 31080, 14), - to = Position(32280, 31102, 14), - }, - exit = Position(32271, 31097, 14), -} - -local lever = BossLever(config) -lever:position(Position(32302, 31087, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/the_last_lore_keeper.lua b/data-otservbr-global/scripts/actions/bosses_levers/the_last_lore_keeper.lua deleted file mode 100644 index d14d9b88d73..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/the_last_lore_keeper.lua +++ /dev/null @@ -1,44 +0,0 @@ -local config = { - boss = { - name = "The Last Lore Keeper", - position = Position(31987, 32839, 14), - }, - timeToFightAgain = ParseDuration("14d") / 1000, - timeToDefeat = ParseDuration("17m") / 1000, - requiredLevel = 250, - playerPositions = { - { pos = Position(32018, 32844, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32019, 32844, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32020, 32844, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32018, 32845, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32019, 32845, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32020, 32845, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32018, 32846, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32019, 32846, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32020, 32846, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32018, 32847, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32019, 32847, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32020, 32847, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32018, 32848, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32019, 32848, 14), teleport = Position(31984, 32851, 14) }, - { pos = Position(32020, 32848, 14), teleport = Position(31984, 32851, 14) }, - }, - monsters = { - { name = "bound astral power", pos = Position(31973, 32840, 15) }, - { name = "bound astral power", pos = Position(31973, 32856, 15) }, - { name = "bound astral power", pos = Position(31989, 32856, 15) }, - { name = "bound astral power", pos = Position(31989, 32840, 15) }, - { name = "a shielded astral glyph", pos = Position(31986, 32840, 14) }, - { name = "the distorted astral source", pos = Position(31986, 32823, 15) }, - { name = "an astral glyph", pos = Position(31989, 32823, 15) }, - }, - specPos = { - from = Position(31968, 32821, 14), - to = Position(32004, 32865, 15), - }, - exit = Position(32035, 32859, 14), -} - -local lever = BossLever(config) -lever:position(Position(32019, 32843, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/the_thorn_knight.lua b/data-otservbr-global/scripts/actions/bosses_levers/the_thorn_knight.lua deleted file mode 100644 index b48a07e44e1..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/the_thorn_knight.lua +++ /dev/null @@ -1,30 +0,0 @@ -local config = { - boss = { - name = "The Enraged Thorn Knight", - createFunction = function() - return Game.createMonster("Mounted Thorn Knight", Position(32624, 32880, 14), true, true) - end, - }, - requiredLevel = 250, - playerPositions = { - { pos = Position(32657, 32877, 14), teleport = Position(32624, 32886, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32657, 32878, 14), teleport = Position(32624, 32886, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32657, 32879, 14), teleport = Position(32624, 32886, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32657, 32880, 14), teleport = Position(32624, 32886, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(32657, 32881, 14), teleport = Position(32624, 32886, 14), effect = CONST_ME_TELEPORT }, - }, - onUseExtra = function(player) - for d = 1, 6 do - Game.createMonster("possessed tree", Position(math.random(32619, 32629), math.random(32877, 32884), 14), true, true) - end - end, - specPos = { - from = Position(32613, 32869, 14), - to = Position(32636, 32892, 14), - }, - exit = Position(32678, 32888, 14), -} - -local lever = BossLever(config) -lever:position(Position(32657, 32876, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/the_time_guardian.lua b/data-otservbr-global/scripts/actions/bosses_levers/the_time_guardian.lua deleted file mode 100644 index 386bce7d94d..00000000000 --- a/data-otservbr-global/scripts/actions/bosses_levers/the_time_guardian.lua +++ /dev/null @@ -1,27 +0,0 @@ -local config = { - boss = { - name = "The Time Guardian", - position = Position(32977, 31662, 14), - }, - requiredLevel = 250, - playerPositions = { - { pos = Position(33010, 31660, 14), teleport = Position(32977, 31667, 14) }, - { pos = Position(33010, 31661, 14), teleport = Position(32977, 31667, 14) }, - { pos = Position(33010, 31662, 14), teleport = Position(32977, 31667, 14) }, - { pos = Position(33010, 31663, 14), teleport = Position(32977, 31667, 14) }, - { pos = Position(33010, 31664, 14), teleport = Position(32977, 31667, 14) }, - }, - monsters = { - { name = "The Freezing Time Guardian", pos = Position(32975, 31664, 13) }, - { name = "The Blazing Time Guardian", pos = Position(32980, 31664, 13) }, - }, - specPos = { - from = Position(32967, 31654, 14), - to = Position(32989, 31677, 14), - }, - exit = Position(32870, 32724, 14), -} - -local lever = BossLever(config) -lever:position(Position(33010, 31659, 14)) -lever:register() diff --git a/data-otservbr-global/scripts/actions/farmine/boat.lua b/data-otservbr-global/scripts/actions/farmine/boat.lua deleted file mode 100644 index 6a1e381c1e5..00000000000 --- a/data-otservbr-global/scripts/actions/farmine/boat.lua +++ /dev/null @@ -1,36 +0,0 @@ -local boats = { - { pos = { x = 33344, y = 31349, z = 7 }, destination = Position(33326, 31351, 7), unlockShortcut = Storage.TheSecretLibrary.ShortcutToBastion }, - { pos = { x = 33373, y = 31309, z = 7 }, destination = Position(33382, 31292, 7) }, - { pos = { x = 33382, y = 31294, z = 7 }, destination = Position(33374, 31310, 7) }, - { pos = { x = 33328, y = 31352, z = 7 }, destination = Position(33346, 31348, 7), access = Storage.TheSecretLibrary.ShortcutToBastion }, -} - -local boat = Action() - -function boat.onUse(player, item, fromPosition, itemEx, toPosition) - for b = 1, #boats do - if item:getPosition() == Position(boats[b].pos) then - if boats[b].unlockShortcut then - if player:getStorageValue(boats[b].unlockShortcut) < 1 then - player:setStorageValue(boats[b].unlockShortcut, 1) - end - end - if boats[b].access then - if player:getStorageValue(boats[b].access) == 1 then - player:teleportTo(boats[b].destination) - player:getPosition():sendMagicEffect(CONST_ME_WATERSPLASH) - return true - end - else - player:teleportTo(boats[b].destination) - player:getPosition():sendMagicEffect(CONST_ME_WATERSPLASH) - return true - end - end - end -end - -for a = 1, #boats do - boat:position(boats[a].pos) -end -boat:register() diff --git a/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua b/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua index 0fb998a9756..f5d878df284 100644 --- a/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua +++ b/data-otservbr-global/scripts/actions/object/imbuement_shrine.lua @@ -1,7 +1,7 @@ local imbuement = Action() function imbuement.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if configManager.getBoolean(configKeys.TOGGLE_IMBUEMENT_SHRINE_STORAGE) and player:getStorageValue(Storage.ForgottenKnowledge.Tomes) ~= 1 then + if configManager.getBoolean(configKeys.TOGGLE_IMBUEMENT_SHRINE_STORAGE) and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Tomes) ~= 1 then return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You did not collect enough knowledge from the ancient Shapers. Visit the Shaper temple in Thais for help.") end diff --git a/data-otservbr-global/scripts/actions/other/bed_modification_kits.lua b/data-otservbr-global/scripts/actions/other/bed_modification_kits.lua deleted file mode 100644 index 4dd68ff834d..00000000000 --- a/data-otservbr-global/scripts/actions/other/bed_modification_kits.lua +++ /dev/null @@ -1,54 +0,0 @@ -local beds = { - [831] = { { 734, 735 }, { 736, 737 } }, -- green kit - [832] = { { 742, 743 }, { 744, 745 } }, -- yellow kit - [833] = { { 738, 739 }, { 740, 741 } }, -- red kit - [834] = { { 2487, 2488 }, { 2493, 2494 } }, -- removal kit - [17972] = { { 17917, 17918 }, { 17919, 17920 } }, -- canopy kit -} - -local function internalBedTransform(item, target, toPosition, itemArray) - target:transform(itemArray[1]) - target:getPosition():sendMagicEffect(CONST_ME_POFF) - - toPosition:getTile():getItemByType(ITEM_TYPE_BED):transform(itemArray[2]) - toPosition:sendMagicEffect(CONST_ME_POFF) - - item:remove() -end - -local bedModificationKits = Action() - -function bedModificationKits.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local newBed = beds[item.itemid] - if not newBed then - return false - end - - local tile = toPosition:getTile() - if not tile or not tile:getHouse() then - return false - end - - if target.itemid == newBed[1][1] or target.itemid == newBed[2][1] then - player:sendTextMessage(MESSAGE_FAILURE, "You already have this bed modification.") - return true - end - - for kit, bed in pairs(beds) do - if bed[1][1] == target.itemid or table.contains({ 2491, 5501, 15506 }, target.itemid) then - toPosition:sendMagicEffect(CONST_ME_POFF) - toPosition.y = toPosition.y + 1 - internalBedTransform(item, target, toPosition, newBed[1]) - break - elseif bed[2][1] == target.itemid or table.contains({ 2489, 5499, 15508 }, target.itemid) then - toPosition:sendMagicEffect(CONST_ME_POFF) - toPosition.x = toPosition.x + 1 - internalBedTransform(item, target, toPosition, newBed[2]) - break - end - end - return true -end - -bedModificationKits:id(831, 832, 833, 834, 17972) -bedModificationKits:register() diff --git a/data-otservbr-global/scripts/actions/other/dolls.lua b/data-otservbr-global/scripts/actions/other/dolls.lua deleted file mode 100644 index 32864dcd109..00000000000 --- a/data-otservbr-global/scripts/actions/other/dolls.lua +++ /dev/null @@ -1,106 +0,0 @@ -local dolls = { - [5080] = { "Hug me." }, - [5668] = { - "It's not winning that matters, but winning in style.", - "Today's your lucky day. Probably.", - "Do not meddle in the affairs of dragons, for you are crunchy and taste good with ketchup.", - "That is one stupid question.", - "You'll need more rum for that.", - "Do or do not. There is no try.", - "You should do something you always wanted to.", - "If you walk under a ladder and it falls down on you it probably means bad luck.", - "Never say 'oops'. Always say 'Ah, interesting!'", - "Five steps east, fourteen steps south, two steps north and seventeen steps west!", - }, - [6566] = { - "Fchhhhhh!", - "Zchhhhhh!", - "Grooaaaaar*cough*", - "Aaa... CHOO!", - "You... will.... burn!!", - }, - [6387] = { "Merry Christmas |PLAYERNAME|." }, - [6511] = { - "Ho ho ho", - "Jingle bells, jingle bells...", - "Have you been naughty?", - "Have you been nice?", - "Merry Christmas!", - "Can you stop squeezing me now... I'm starting to feel a little sick.", - }, - [8146] = { "ARE YOU PREPARED TO FACE YOUR DESTINY?" }, - [8149] = { - "Weirdo, you're a weirdo! Actually all of you are!", - "Pie for breakfast, pie for lunch and pie for dinner!", - "All hail the control panel!", - "I own, Tibiacity owns, perfect match!", - "Hug me! Feed me! Hail me!", - }, - [8153] = { - "It's news to me.", - "News, updated as infrequently as possible!", - "Extra! Extra! Read all about it!", - "Fresh off the press!", - }, - [8154] = { - "Hail TibiaNordic!", - "So cold..", - "Run, mammoth!", - }, - [21435] = { - "I can hear their whisperings... Revenge!", - "You shall feel pain and terror, |PLAYERNAME|", - "I do not need a sword to slaughter you", - "My sword is broken, but my spirit is not dead", - "I can say 469 and more...", - "My dark magic lies on tibialatina.wikia.com", - }, - [21962] = { "Hail Tibia Brasileiros! (União&Força)" }, - [32918] = { - "COME HERE! FREE ITEMS FOR EVERYONE!", - "DON'T BE AFRAID! I AM COMING IN PEACE!", - "BOW TO THE POWER OF THE RUTHLESS SEVEN!", - "Slay your friends and I will spare you!", - }, -} - -local doll = Action() - -function doll.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local sounds = dolls[item.itemid] - if not sounds then - return false - end - - if fromPosition.x == CONTAINER_POSITION then - fromPosition = player:getPosition() - end - - local random = math.random(#sounds) - local sound = sounds[random] - if item.itemid == 6566 then - if random == 3 then - fromPosition:sendMagicEffect(CONST_ME_POFF) - elseif random == 4 then - fromPosition:sendMagicEffect(CONST_ME_FIREAREA) - elseif random == 5 then - doTargetCombatHealth(0, player, COMBAT_PHYSICALDAMAGE, -1, -1, CONST_ME_EXPLOSIONHIT) - end - elseif item.itemid == 5668 then - fromPosition:sendMagicEffect(CONST_ME_MAGIC_RED) - item:transform(item.itemid + 1) - item:decay() - elseif item.itemid == 6387 then - fromPosition:sendMagicEffect(CONST_ME_SOUND_YELLOW) - end - - sound = sound:gsub("|PLAYERNAME|", player:getName()) - player:say(sound, TALKTYPE_MONSTER_SAY, false, 0, fromPosition) - return true -end - -for index, value in pairs(dolls) do - doll:id(index) -end - -doll:register() diff --git a/data-otservbr-global/scripts/actions/other/others/quest_system2.lua b/data-otservbr-global/scripts/actions/other/others/quest_system2.lua index a187810b3bc..89b61977dfc 100644 --- a/data-otservbr-global/scripts/actions/other/others/quest_system2.lua +++ b/data-otservbr-global/scripts/actions/other/others/quest_system2.lua @@ -309,7 +309,7 @@ This page seems to be part of a book about ancient rituals, mystic incantations name = "Falcon Bastion Access", }, }, - storage = Storage.TheSecretLibrary.FalconBastionAccess, + storage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionAccess, }, [20002] = { items = { diff --git a/data-otservbr-global/scripts/actions/other/surprise_bag.lua b/data-otservbr-global/scripts/actions/other/surprise_bag.lua deleted file mode 100644 index 052fc987c61..00000000000 --- a/data-otservbr-global/scripts/actions/other/surprise_bag.lua +++ /dev/null @@ -1,103 +0,0 @@ -local config = { - [6570] = { -- bluePresent - { 3598, 10 }, - { 6393, 3 }, - 6279, - 6574, - 6578, - 6575, - 6577, - 6569, - 6576, - 6572, - 2995, - 14027, - 14681, - }, - [6571] = { -- redPresent - 6574, - 3079, - 6393, - 6576, - 6578, - 2995, - 14027, - 3036, - 5944, - 3386, - 3420, - 3039, - 5080, - 2993, - 3392, - 3057, - 5791, - }, - [8853] = { -- surpriseBag - { 3031, 10 }, - 123, - 2995, - 2397, - 651, - 3218, - 6574, - 6393, - 7377, - 3578, - 8778, - }, - [14751] = { -- surpriseBag - { 9642, 15 }, - { 3581, 15 }, - 5917, - 3273, - 10302, - 9019, - 5928, - 5926, - 5927, - 6095, - 5918, - 6097, - 6098, - 5461, - 5090, - }, - [14759] = { -- surpriseBag - { 6569, 10 }, - { 6541, 10 }, - { 6542, 10 }, - { 6543, 10 }, - { 6544, 10 }, - { 6545, 10 }, - 6574, - 4839, - 6570, - 6571, - 3215, - }, -} - -local surpriseBag = Action() - -function surpriseBag.onUse(cid, item, fromPosition, itemEx, toPosition) - local present = config[item.itemid] - if not present then - return false - end - - local count = 1 - local gift = present[math.random(1, #present)] - if type(gift) == "table" then - count = math.random(1, gift[2]) - gift = gift[1] - end - - Player(cid):addItem(gift, count) - Item(item.uid):remove(1) - fromPosition:sendMagicEffect(CONST_ME_GIFT_WRAPS) - return true -end - -surpriseBag:id(6570, 6571, 8853, 14751, 14759) -surpriseBag:register() diff --git a/data-otservbr-global/scripts/actions/other/surprise_box.lua b/data-otservbr-global/scripts/actions/other/surprise_box.lua deleted file mode 100644 index 94fdb95eb2d..00000000000 --- a/data-otservbr-global/scripts/actions/other/surprise_box.lua +++ /dev/null @@ -1,31 +0,0 @@ -local prize = { - [1] = { chance = 1, id = 3246, amount = 1 }, - [2] = { chance = 2, id = 10227, amount = 1 }, - [3] = { chance = 3, id = 11588, amount = 1 }, - [4] = { chance = 4, id = 3549, amount = 1 }, - [5] = { chance = 5, id = 3420, amount = 1 }, - [6] = { chance = 10, id = ITEM_CRYSTAL_COIN, amount = 17 }, - [7] = { chance = 20, id = ITEM_GOLD_COIN, amount = 1 }, - [8] = { chance = 30, id = ITEM_CRYSTAL_COIN, amount = 1 }, - [9] = { chance = 40, id = ITEM_GOLD_COIN, amount = 50 }, - [10] = { chance = 50, id = ITEM_PLATINUM_COIN, amount = 15 }, - [11] = { chance = 90, id = ITEM_GOLD_COIN, amount = 80 }, -} - -local surpriseBox = Action() - -function surpriseBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) - for i = 1, #prize do - local number = math.random() * 100 - if prize[i].chance > 100 - number then - player:getPosition():sendMagicEffect(CONST_ME_POFF) - player:addItem(prize[i].id, prize[i].amount) - item:remove() - break - end - end - return true -end - -surpriseBox:id(12045) -surpriseBox:register() diff --git a/data-otservbr-global/scripts/actions/other/teleport.lua b/data-otservbr-global/scripts/actions/other/teleport.lua deleted file mode 100644 index 7e763f00594..00000000000 --- a/data-otservbr-global/scripts/actions/other/teleport.lua +++ /dev/null @@ -1,19 +0,0 @@ -local ladderTable = Game.getLadderIds() - -local upFloorIds = ladderTable - -local teleport = Action() - -function teleport.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if table.contains(upFloorIds, item.itemid) then - fromPosition:moveUpstairs() - else - fromPosition.z = fromPosition.z + 1 - end - player:teleportTo(fromPosition, false) - return true -end - -teleport:id(435) -teleport:id(unpack(ladderTable)) -teleport:register() diff --git a/data-otservbr-global/scripts/actions/other/transform_to.lua b/data-otservbr-global/scripts/actions/other/transform_to.lua deleted file mode 100644 index 5257544eb60..00000000000 --- a/data-otservbr-global/scripts/actions/other/transform_to.lua +++ /dev/null @@ -1,484 +0,0 @@ -local voices = { - [23708] = "Au au!", - [23443] = "Grooaarr!", -} - -local transformItems = { - [2062] = 2063, - [2063] = 2062, -- sacred statue - [2064] = 2065, - [2065] = 2064, -- sacred statue - [2108] = 2109, - [2109] = 2108, -- street lamp - [2334] = 2335, - [2335] = 2334, -- table - [2336] = 2337, - [2337] = 2336, -- table - [2338] = 2339, - [2339] = 2338, -- table - [2340] = 2341, - [2341] = 2340, -- table - [2535] = 2536, - [2536] = 2535, -- oven - [2537] = 2538, - [2538] = 2537, -- oven - [2539] = 2540, - [2540] = 2539, -- oven - [2541] = 2542, - [2542] = 2541, -- oven - [2660] = 2661, - [2661] = 2660, -- cuckoo clock - [2662] = 2663, - [2663] = 2662, -- cuckoo clock - [2772] = 2773, - [2773] = 2772, -- lever - [2911] = 2912, - [2912] = 2911, -- candelabrum - [2914] = 2915, - [2915] = 2914, -- lamp - [2917] = 2918, - [2918] = 2917, -- candlestick - [2920] = 2921, - [2921] = 2920, -- torch - [2922] = 2923, - [2923] = 2922, -- torch - [2924] = 2925, - [2925] = 2924, -- torch - [2928] = 2929, - [2929] = 2928, -- torch bearer - [2930] = 2931, - [2931] = 2930, -- torch bearer - [2934] = 2935, - [2935] = 2934, -- table lamp - [2977] = 2978, - [2978] = 2977, -- pumpkinhead - [3046] = 3047, - [3047] = 3046, -- magic light wand - [3481] = 3482, -- closed trap - [5812] = 5813, - [5813] = 5812, -- skull candle - [6488] = 6489, - [6489] = 6488, -- christmas branch - [7058] = 7059, - [7059] = 7058, -- skull pillar - [7856] = 7857, - [7857] = 7856, -- chimney - [7858] = 7859, - [7859] = 7858, -- chimney - [7860] = 7861, - [7861] = 7860, -- chimney - [7862] = 7863, - [7863] = 7862, -- chimney - [8659] = 8660, - [8660] = 8659, -- street lamp - [8661] = 8662, - [8662] = 8661, -- street lamp - [8663] = 8664, - [8664] = 8663, -- street lamp - [8665] = 8666, - [8666] = 8665, -- street lamp - [8832] = 8833, - [8833] = 8832, -- wall lamp - [8834] = 8835, - [8835] = 8834, -- wall lamp - [17411] = 17412, - [17412] = 17411, -- street lamp - [20280] = 20281, - [20281] = 20280, -- beacon - [20498] = 20497, - [20497] = 20498, -- street lamp - [20500] = 20499, - [20499] = 20500, -- street lamp - [20501] = 20502, - [20502] = 20501, -- candle - [20503] = 20504, - [20504] = 20503, -- candle - [22153] = 22154, - [22154] = 22153, -- skull - [22764] = 22765, - [22765] = 22764, -- ferumbras staff - [23434] = 23436, - [23436] = 23434, -- predador lamp - [23435] = 23437, - [23437] = 23435, -- predador lamp - [23438] = 23440, - [23440] = 23438, -- protectress lamp - [23439] = 23441, - [23441] = 23439, -- protectress lamp - [23442] = 23443, - [23443] = 23442, -- baby dragon - [23444] = 23445, - [23445] = 23444, -- hamster wheel - [23451] = 23452, - [23452] = 23451, -- cat in a basket - [23485] = 23486, - [23486] = 23485, -- barrel - [23708] = 23709, - [23709] = 23708, -- dog house - [24432] = 24433, - [24433] = 24432, -- parrot - [24434] = 24436, - [24435] = 24434, -- skull lamp - [25212] = 25210, - [25211] = 25212, -- vengothic lamp - [26078] = 26079, -- spider terrarium - [26081] = 26083, - [26083] = 26081, -- hrodmiran weapons rack - [26084] = 26082, - [26082] = 26084, -- hrodmiran weapons rack side - [26171] = 26169, - [26172] = 26170, -- snake terrarium - [26173] = 26175, - [26174] = 26176, -- demon pet - [27667] = 27668, -- light of change empty to red - [27668] = 27669, -- light of change red to green - [27669] = 27670, -- light of change green to blue - [27670] = 27667, -- light of change blue to empty - [27671] = 27673, -- torch of change empty to red - [27673] = 27674, -- torch of change red to green - [27674] = 27675, -- torch of change green to blue - [27675] = 27671, -- torch of change blue to empty - [27683] = 27685, - [27684] = 27686, -- alchemistic scales - [27687] = 27688, - [27688] = 27687, -- pile of alchemistic books - [27691] = 27692, - [27692] = 27691, -- ferumbras bust - [27693] = 27694, - [27694] = 27693, -- ferumbras bust - [27986] = 27988, - [27988] = 27986, -- bonelord statue - [27987] = 27989, - [27989] = 27987, -- bonelord statue - [27996] = 27998, - [27998] = 27996, -- scholar bust - [27997] = 27999, - [27999] = 27997, -- scholar bust - [28000] = 28002, - [28002] = 28000, -- scholar bust - [28001] = 28003, - [28003] = 28001, -- scholar bust - [28674] = 28675, - [28675] = 28674, -- anglerfish lamp - [28690] = 28691, - [28692] = 28693, -- baby rotworm - [28694] = 28695, --fennec - [28915] = 28916, - [28917] = 28918, -- adamant shield - [28920] = 28921, - [28921] = 28920, -- fluorescent fungi - [28922] = 28923, - [28923] = 28922, -- luminescent fungi - [28924] = 28925, - [28925] = 28924, -- glowing sulphur fungi - [28926] = 28927, - [28927] = 28926, -- gloomy poisonous fungi - [30229] = 30230, - [30230] = 30231, -- festive table - [30231] = 30229, -- festive table - [30233] = 30234, - [30234] = 30233, -- festive fireplace - [30235] = 30236, - [30236] = 30235, -- festive fireplace - [30237] = 30238, - [30238] = 30237, -- festive tree - [30248] = 30249, - [30249] = 30248, -- festive pyramid - [30362] = 30365, -- Badbara - [30363] = 30366, -- Tearesa - [30364] = 30367, -- Cryana - [31196] = 31197, - [31197] = 31196, -- crystal lamp - [31213] = 31215, - [31215] = 31213, -- idol lamp - [31214] = 31216, - [31216] = 31214, -- idol lamp side - [31462] = 31463, - [31464] = 31465, -- jousting eagle baby - [31674] = 31675, -- omniscient owl - [31681] = 31682, -- hedgehog - [31683] = 31684, - [31684] = 31683, -- exalted sarcophagus - [31695] = 31696, - [31696] = 31695, -- curly hortensis lamp - [31697] = 31698, - [31698] = 31697, -- little big flower lamp - [31703] = 31704, -- baby unicorn - [32760] = 32758, - [32761] = 32759, -- mini NaBbot - [32784] = 32785, - [32785] = 32784, -- ice chandelier - [32788] = 32789, -- baby seal - [32790] = 32791, - [32792] = 32793, -- baby polar bear - [32897] = 32899, - [32899] = 32897, -- wall lamp - [32900] = 32901, - [32901] = 32900, -- torch bearer - [32902] = 32903, - [32903] = 32902, -- bamboo wall lamp - [32904] = 32905, - [32905] = 32904, -- wall candle - [32907] = 32910, -- guzzlemaw grub - [32908] = 32911, -- baby vulcongra - [32909] = 32912, -- baby brain squid - [33026] = 33047, - [33027] = 33026, -- heart lamp - [33028] = 33048, - [33029] = 33028, -- heart lamp (flower) - [33030] = 33049, - [33031] = 33030, -- heart lamp (small flower) - [33040] = 33042, -- bat - [33331] = 33332, - [33333] = 33334, -- bard doll - [34026] = 34027, -- baby bonelord - [34030] = 34031, - [34031] = 34030, -- artist shelf - [34032] = 34033, - [34033] = 34032, -- artist shelf - [34034] = 34035, - [34035] = 34034, -- artist table - [34044] = 34045, - [34045] = 34044, -- sculptor shelf - [34046] = 34047, - [34047] = 34046, -- sculptor shelf - [34048] = 34049, - [34049] = 34048, -- sculptor table - [34064] = 34065, - [34065] = 34066, -- sculpture of a noblewoman - [34066] = 34067, - [34067] = 34064, -- sculpture of a noblewoman - [34068] = 34069, - [34069] = 34070, -- sculpture of a noblewoman - [34070] = 34071, - [34071] = 34068, -- sculpture of a noblewoman - [34264] = 34265, - [34266] = 34267, -- Tibiapedia - [34268] = 34269, - [34269] = 34268, -- Baby Munster - [34270] = 34271, - [34271] = 34270, -- glowworms - [34272] = 34273, - [34273] = 34272, -- oven - [34274] = 34275, - [34275] = 34274, -- oven - [34284] = 34285, - [34285] = 34284, -- kitchen table (empty) - [34287] = 34288, - [34288] = 34287, -- kitchen table (empty) - [34286] = 34290, - [34290] = 34286, -- kitchen table - [34289] = 34291, - [34291] = 34289, -- kitchen table - [34300] = 34301, - [34301] = 34300, -- barrel - [34304] = 34305, - [34305] = 34304, -- kitchen lamp - [34326] = 34327, -- wicked witch - [35153] = 35154, -- baby elephant - [35155] = 35157, - [35157] = 35159, -- forge - [35159] = 35155, - [35156] = 35158, -- forge - [35158] = 35160, - [35160] = 35156, -- forge - [35161] = 35162, - [35162] = 35161, -- metal wall lamp - [35163] = 35165, - [35165] = 35163, -- workbench - [35164] = 35166, - [35166] = 35164, -- workbench - [35177] = 35180, - [35180] = 35177, -- grinding wheel - [35178] = 35179, - [35179] = 35178, -- grinding wheel - [35181] = 35183, - [35183] = 35181, -- pair of bellows - [35182] = 35184, - [35184] = 35182, -- pair of bellows - [35185] = 35186, - [35186] = 35185, -- anvil - [35187] = 35188, - [35188] = 35187, -- water bucket - [35909] = 35910, -- chaos critical dice - [36019] = 36020, -- white lion doll - [36478] = 36479, - [36480] = 36481, -- banor doll - [36618] = 36619, - [36619] = 36618, -- volcanic basin - [36620] = 36621, - [36621] = 36620, -- volcanic sphere - [36622] = 36623, - [36623] = 36622, -- volcanic spire - [36624] = 36625, - [36625] = 36624, -- volcanic bulb - [36626] = 36628, - [36628] = 36626, -- volcanic mirror - [36627] = 36629, - [36629] = 36627, -- volcanic mirror - [36638] = 36639, - [36639] = 36638, -- volcanic table - [36640] = 36642, - [36642] = 36644, -- volcanic shelf - [36644] = 36640, - [36641] = 36643, -- volcanic shelf - [36643] = 36645, - [36645] = 36641, -- volcanic shelf - [36646] = 36649, - [36647] = 36650, -- demon baller - [36648] = 36651, - [36653] = 36652, -- demon baller - [36654] = 36646, -- demon baller - [36750] = 36751, - [36754] = 36752, -- falcon pet - [36756] = 36753, -- falcon pet - [36959] = 36960, -- megasylvan plant - [36978] = 36979, - [36979] = 36978, -- magic hat - [36996] = 36997, - [36998] = 36999, -- Luna - [37015] = 37016, - [37016] = 37015, -- yellow shroom lamp - [37017] = 37018, - [37018] = 37017, -- pink shroom lamp - [37021] = 37022, -- dragon plant - [37052] = 37053, - [37053] = 37052, -- bonelord tome - [37054] = 37055, - [37056] = 37057, -- Bella Bonecrusher's doll - [37061] = 37062, - [37063] = 37064, -- Evora - [37111] = 37112, - [37113] = 37114, -- armillary sphere - [37185] = 37186, - [37186] = 37700, -- kraken watcher lamp - [37700] = 37185, -- kraken watcher lamp - [37187] = 37519, - [37519] = 37187, -- kraken buoy lamp - [37188] = 37520, - [37520] = 37188, -- kraken tentacle lamp - [37189] = 37191, - [37191] = 37189, -- kraken shelf - [37190] = 37192, - [37192] = 37190, -- kraken shelf - [37205] = 37206, - [37206] = 37207, -- sculpture of an octoputz - [37207] = 37205, - [37208] = 37209, -- sculpture of an octoputz - [37209] = 37210, - [37210] = 37208, -- sculpture of an octoputz - [37211] = 37212, - [37212] = 37211, -- octoputz - [37543] = 37580, - [37580] = 37543, -- string of fairy lights RYG - [37544] = 37581, - [37581] = 37544, -- string of fairy lights BRG - [37545] = 37582, - [37582] = 37545, -- string of fairy lights BGY - [37557] = 37558, - [37559] = 37560, -- dragon pinata - [37743] = 37744, - [37745] = 37746, -- draptor doll - [37749] = 37750, - [37750] = 37749, -- dark oracle - [37806] = 37807, - [37807] = 37806, -- zaoan wall lamp - [37808] = 37809, - [37809] = 37808, -- zaoan wall lamps - [37811] = 37813, - [37812] = 37814, -- sculpture of a fox - [38522] = 38524, - [38524] = 38522, -- naga lamp - [38523] = 38525, - [38525] = 38523, -- naga lamp - [38526] = 38528, - [38528] = 38526, -- basin with a glowing flower - [38677] = 38680, - [38704] = 38705, -- beaver of wisdom - [38827] = 38828, - [38828] = 38827, -- wall lamp - [39423] = 39425, - [39425] = 39423, -- knightly table - [39424] = 39426, - [39426] = 39424, -- knightly table - [39427] = 39428, - [39428] = 39427, -- knightly chess table - [39443] = 39444, - [39444] = 39445, -- knightly fire bowl - [39445] = 39443, -- knightly fire bowl - [39498] = 39499, - [39499] = 39498, -- knightly candelabra - [39500] = 39501, - [39501] = 39500, -- knightly candle holder - [39508] = 39509, - [39668] = 39510, -- knightly guard - [39694] = 39696, -- lucky dragon - [39697] = 39698, - [39698] = 39697, -- rainbow torch - [39699] = 39700, - [39700] = 39699, -- rainbow torch - [39701] = 39702, - [39702] = 39701, -- rainbow torch - [39757] = 39758, -- yeti doll - [39759] = 39760, - [39761] = 39762, -- the gods' twilight doll - [39772] = 39773, - [39773] = 39774, -- flower table - [39774] = 39772, -- flower table - [39793] = 39794, - [39794] = 39793, -- turquoise flower lamp - [39795] = 39796, - [39796] = 39795, -- purple flower lamp - [39801] = 39802, - [39802] = 39801, -- wall leaves - [39803] = 39804, - [39804] = 39803, -- tendrils - [39805] = 39806, - [39807] = 39808, -- water nymph - [39810] = 39809, -- water nymph - [42271] = 42272, - [42272] = 42271, -- seafarer table - [42291] = 42292, - [42292] = 42291, -- seashell lamp - [42293] = 42294, - [42294] = 42293, -- seashell lamp - [42295] = 42296, - [42296] = 42295, -- tentacle lamp - [42297] = 42298, - [42298] = 42297, -- tentacle lamp - [42299] = 42300, - [42300] = 42299, -- sea-devil wall lamp - [42301] = 42302, - [42302] = 42301, -- seafood bucket - [42324] = 42326, - [42326] = 42324, -- opulent table - [42325] = 42327, - [42327] = 42325, -- opulent table - [42346] = 42347, - [42347] = 42346, -- opulent floor lamp - [42348] = 42349, - [42349] = 42348, -- opulent floor lamp - [42363] = 42364, -- djinn lamp - [42365] = 42366, -- djinn lamp -} - -local transformTo = Action() - -function transformTo.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if voices[item:getId()] then - local spectators = Game.getSpectators(fromPosition, false, true, 3, 3) - for i = 1, #spectators do - player:say(voices[item:getId()], TALKTYPE_MONSTER_SAY, false, spectators[i], fromPosition) - end - end - - item:transform(transformItems[item.itemid]) - item:decay() - return true -end - -for index, value in pairs(transformItems) do - transformTo:id(index) -end - -transformTo:register() diff --git a/data-otservbr-global/scripts/actions/other/vessels.lua b/data-otservbr-global/scripts/actions/other/vessels.lua deleted file mode 100644 index b1f0701becb..00000000000 --- a/data-otservbr-global/scripts/actions/other/vessels.lua +++ /dev/null @@ -1,30 +0,0 @@ -local config = { - [37572] = CONST_ME_GAZHARAGOTH, -- vessel of Gaz'haragoth - [37573] = CONST_ME_FERUMBRAS_1, -- vessel of Ferumbras - [37574] = CONST_ME_MAD_MAGE, -- vessel of the Mad Mage - [37575] = CONST_ME_HORESTIS, -- vessel of Horestis - [37576] = CONST_ME_DEVOVORGA, -- vessel of Devovorga -} - -local vessels = Action() - -function vessels.onUse(player, item, fromPosition, itemEx, toPosition) - local vessel = config[item.itemid] - local tile = toPosition:getTile() - if not vessel or not player then - return false - end - if not tile:isWalkable() then - player:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM) - else - item:remove(1) - toPosition:sendMagicEffect(vessel) - end - return true -end - -for index, value in pairs(config) do - vessels:id(index) -end -vessels:allowFarUse(true) -vessels:register() diff --git a/data-otservbr-global/scripts/actions/valuables/random_items.lua b/data-otservbr-global/scripts/actions/valuables/random_items.lua index 9e62086a972..2772ac859ce 100644 --- a/data-otservbr-global/scripts/actions/valuables/random_items.lua +++ b/data-otservbr-global/scripts/actions/valuables/random_items.lua @@ -172,6 +172,13 @@ local config = { }, effect = CONST_ME_CRAPS, }, + [26186] = { -- mystery box + chances = { + { from = 0, to = 5001, itemId = 25361 }, -- blood of the mountain + { from = 5002, to = 10001, itemId = 25360 }, -- heart of the mountain + }, + effect = CONST_ME_CRAPS, + }, [27654] = { -- surprise jar chances = { { from = 0, to = 2500, itemId = 3041 }, diff --git a/data-otservbr-global/scripts/creaturescripts/customs/freequests.lua b/data-otservbr-global/scripts/creaturescripts/customs/freequests.lua index bf0e1430635..bfeac7acad0 100644 --- a/data-otservbr-global/scripts/creaturescripts/customs/freequests.lua +++ b/data-otservbr-global/scripts/creaturescripts/customs/freequests.lua @@ -1,392 +1,354 @@ local stage = configManager.getNumber(configKeys.FREE_QUEST_STAGE) local questTable = { - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 2 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 4 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 7 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 9 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 12 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.Shooting, storageValue = 5 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 16 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 20 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 23 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.QuestLineComplete, storageValue = 2 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.Rank, storageValue = 1440 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.Warzone1Access, storageValue = 2 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.Warzone2Access, storageValue = 2 }, - { storage = Storage.Quest.U9_60.BigfootsBurden.Warzone3Access, storageValue = 2 }, - { storage = Storage.DangerousDepths.Questline, storageValue = 10 }, - { storage = Storage.DangerousDepths.Access.LavaPumpWarzoneVI, storageValue = 10 }, - { storage = Storage.DangerousDepths.Access.LavaPumpWarzoneV, storageValue = 10 }, - { storage = Storage.DangerousDepths.Access.LavaPumpWarzoneIV, storageValue = 30 }, - { storage = Storage.DangerousDepths.Dwarves.Status, storageValue = 10 }, - { storage = Storage.DangerousDepths.Scouts.Status, storageValue = 10 }, - { storage = Storage.DangerousDepths.Gnomes.Status, storageValue = 10 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Questline, storageValue = 51 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission01, storageValue = 6 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission02, storageValue = 8 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission03, storageValue = 6 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission04, storageValue = 6 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission05, storageValue = 8 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission06, storageValue = 5 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission07, storageValue = 5 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission08, storageValue = 4 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission09, storageValue = 2 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission10, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe01, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe02, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe03, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe04, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedDan, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedBill, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedFred, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.AlchemistFormula, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.BadSide, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.GoodSide, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.MrWestDoor, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.MrWestStatus, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.TamerinStatus, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.MorikSummon, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraState, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraSplasher, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraSharptooth, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraInky, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.MatrixState, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.NotesPalimuth, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.NotesAzerus, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToAzerus, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToBog, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToLastFight, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToMatrix, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToQuara, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Questline, storageValue = 7 }, - { storage = Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Minotaurs.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Minotaurs.BossTimer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.Stone1, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.Stone2, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.Stone3, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.Answer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.MotA.QuestionId, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.sulphur, storageValue = 4 }, - { storage = Storage.CultsOfTibia.Barkless.Tar, storageValue = 3 }, - { storage = Storage.CultsOfTibia.Barkless.Ice, storageValue = 3 }, - { storage = Storage.CultsOfTibia.Barkless.Objects, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.Temp, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Orcs.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Orcs.LookType, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Orcs.BossTimer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Life.Mission, storageValue = 7 }, - { storage = Storage.CultsOfTibia.Life.BossTimer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Humans.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Humans.Vaporized, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Humans.Decaying, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Humans.BossTimer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.Mission, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.Monsters, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.Exorcisms, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.Time, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.BossTimer, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Minotaurs.EntranceAccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Minotaurs.AccessDoor, storageValue = 1 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 1 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 4 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 7 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 16 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 26 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 29 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 32 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 35 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 38 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 41 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 43 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 46 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 47 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 50 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 55 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 56 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 58 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 61 }, - { storage = Storage.Quest.U7_6.ExplorerSociety.CalassaQuest, storageValue = 2 }, - { storage = Storage.ForgottenKnowledge.Tomes, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.LastLoreKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.TimeGuardianKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.HorrorKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.DragonkingKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.ThornKnightKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.LloydKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.LadyTenebrisKilled, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessMachine, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessLavaTeleport, storageValue = 1 }, - { storage = Storage.Quest.U8_0.BarbarianTest.Questline, storageValue = 8 }, - { storage = Storage.Quest.U8_0.BarbarianTest.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U8_0.BarbarianTest.Mission02, storageValue = 3 }, - { storage = Storage.Quest.U8_0.BarbarianTest.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Questline, storageValue = 21 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission00, storageValue = 2 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission02, storageValue = 5 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission04, storageValue = 6 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission05, storageValue = 3 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding01, storageValue = 1 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding02, storageValue = 1 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding03, storageValue = 1 }, - { storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.StrangeSymbols, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.Faction.Greeting, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.Faction.MaridDoor, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.Faction.EfreetDoor, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Start, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission02, storageValue = 3 }, - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Start, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission01, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission02, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.RataMari, storageValue = 2 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.TheWayToYalahar, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.TownsCounter, storageValue = 5 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.AbDendriel, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Darashia, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Venore, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Ankrahmun, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.PortHope, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Thais, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.LibertyBay, storageValue = 1 }, - { storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Carlin, storageValue = 1 }, - { storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.DefaultStart, storageValue = 1 }, - { storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.GoingDown, storageValue = 1 }, - { storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.WayToBeregar, storageValue = 1 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Questline, storageValue = 40 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission02, storageValue = 5 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission04, storageValue = 2 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission05, storageValue = 6 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission06, storageValue = 8 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission07, storageValue = 3 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission08, storageValue = 4 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission09, storageValue = 2 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission10, storageValue = 2 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission11, storageValue = 2 }, - { storage = Storage.Quest.U8_0.TheIceIslands.Mission12, storageValue = 6 }, - { storage = Storage.Quest.U8_0.TheIceIslands.yakchalDoor, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Questline, storageValue = 25 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission01, storageValue = 7 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission02, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission03, storageValue = 6 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission04, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission05, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission06, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission07, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.GrofGuard, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.KulagGuard, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.TimGuard, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.WalterGuard, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheInquisitionQuest.StorkusVampiredust, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Questline, storageValue = 29 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission02[1], storageValue = 4 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission04, storageValue = 2 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05[1], storageValue = 2 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission06, storageValue = 5 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission07[1], storageValue = 2 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission08, storageValue = 2 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission09[1], storageValue = 3 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission10[1], storageValue = 2 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission10.MagicCarpetDoor, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.TomeofKnowledge, storageValue = 12 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver1, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver2, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver3, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.KingTibianus, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Leeland, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Angus, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Wyrdin, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Telas, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Humgolf, storageValue = 1 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.DefaultStart, storageValue = 3 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.TheGovernorDaughter, storageValue = 3 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.TheErrand, storageValue = 2 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToMeriana, storageValue = 1 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.APoemForTheMermaid, storageValue = 3 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.ADjinnInLove, storageValue = 5 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToLagunaIsland, storageValue = 1 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToGoroma, storageValue = 1 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.Shipwrecked, storageValue = 2 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.DragahsSpellbook, storageValue = 1 }, - { storage = Storage.Quest.U7_8.TheShatteredIsles.TheCounterspell, storageValue = 4 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Questline, storageValue = 1 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission01, storageValue = 2 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission02, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission04, storageValue = 8 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission05, storageValue = 2 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission06, storageValue = 4 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission07, storageValue = 2 }, - { storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission08, storageValue = 1 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission01, storageValue = 1 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission01, storageValue = 2 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission02, storageValue = 5 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission04, storageValue = 3 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission05, storageValue = 3 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission06, storageValue = 2 }, - { storage = Storage.Quest.U8_1.TheTravellingTrader.Mission07, storageValue = 1 }, - { storage = Storage.Quest.U8_0.BarbarianArena.QuestLogGreenhorn, storageValue = 1 }, - { storage = Storage.Quest.U8_1.TibiaTales.DefaultStart, storageValue = 1 }, - { storage = Storage.Quest.U8_1.TibiaTales.ToAppeaseTheMightyQuest, storageValue = 1 }, - { storage = 12450, storageValue = 6 }, - { storage = 12330, storageValue = 1 }, - { storage = 12332, storageValue = 13 }, - { storage = 12333, storageValue = 3 }, - { storage = Storage.Quest.U7_8.FriendsAndTraders.DefaultStart, storageValue = 1 }, - { storage = Storage.Quest.U7_8.FriendsAndTraders.TheSweatyCyclops, storageValue = 2 }, - { storage = Storage.Quest.U7_8.FriendsAndTraders.TheMermaidMarina, storageValue = 2 }, - { storage = Storage.Quest.U7_8.FriendsAndTraders.TheBlessedStake, storageValue = 12 }, - { storage = 100157, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Questline, storageValue = 29 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission01, storageValue = 3 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission02, storageValue = 3 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission03, storageValue = 3 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission04, storageValue = 3 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission05, storageValue = 3 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission06, storageValue = 4 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission07, storageValue = 6 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission08, storageValue = 2 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission09, storageValue = 2 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission10, storageValue = 1 }, - { storage = Storage.Quest.U7_6.TheApeCity.Started, storageValue = 1 }, - { storage = Storage.Quest.U7_6.TheApeCity.Questline, storageValue = 18 }, - { storage = Storage.BanutaSecretTunnel.DeeperBanutaShortcut, storageValue = 1 }, - { storage = Storage.Quest.U10_50.OramondQuest.QuestLine, storageValue = 1 }, - { storage = Storage.Quest.U10_50.OramondQuest.ToTakeRoots.Mission, storageValue = 3000 }, - { storage = Storage.DangerousDepths.Questline, storageValue = 1 }, - { storage = Storage.DangerousDepths.Dwarves.Home, storageValue = 2 }, - { storage = Storage.DangerousDepths.Dwarves.Subterranean, storageValue = 2 }, - { storage = Storage.DangerousDepths.Gnomes.Measurements, storageValue = 2 }, - { storage = Storage.DangerousDepths.Gnomes.Ordnance, storageValue = 3 }, - { storage = Storage.DangerousDepths.Gnomes.Charting, storageValue = 2 }, - { storage = Storage.DangerousDepths.Scouts.Growth, storageValue = 2 }, - { storage = Storage.DangerousDepths.Scouts.Diremaw, storageValue = 2 }, - { storage = Storage.Quest.U11_40.ThreatenedDreams.QuestLine, storageValue = 1 }, - { storage = Storage.Quest.U11_40.ThreatenedDreams.Mission01[1], storageValue = 16 }, - { storage = Storage.Quest.U11_40.ThreatenedDreams.Mission02.KroazurAccess, storageValue = 1 }, - { storage = Storage.Quest.U9_80.AdventurersGuild.QuestLine, storageValue = 1 }, - { storage = Storage.Quest.U10_80.TheGreatDragonHunt.WarriorSkeleton, storageValue = 1 }, - { storage = Storage.Quest.U10_80.TheGreatDragonHunt.WarriorSkeleton, storageValue = 2 }, - { storage = Storage.Quest.U10_80.TheLostBrotherQuest, storageValue = 3 }, - { storage = Storage.Quest.U10_55.Dawnport.Questline, storageValue = 1 }, - { storage = Storage.Quest.U10_55.Dawnport.GoMain, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessDeath, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessViolet, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessEarth, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessFire, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessIce, storageValue = 1 }, - { storage = Storage.ForgottenKnowledge.AccessGolden, storageValue = 1 }, - { storage = Storage.Quest.U10_80.GrimvaleQuest.AncientFeudDoors, storageValue = 1 }, - { storage = Storage.Quest.U10_80.GrimvaleQuest.AncientFeudShortcut, storageValue = 1 }, - { storage = Storage.Kilmaresh.AccessDoor, storageValue = 1 }, - { storage = Storage.Kilmaresh.CatacombDoors, storageValue = 1 }, - { storage = Storage.Quest.U12_00.TheDreamCourts.AccessDoors, storageValue = 1 }, - { storage = Storage.Quest.U12_00.TheDreamCourts.HauntedHouseAccess, storageValue = 1 }, - { storage = Storage.Quest.U12_00.TheDreamCourts.BuriedCathedralAccess, storageValue = 1 }, - { storage = Storage.Quest.U12_00.TheDreamCourts.DreamScarAccess, storageValue = 1 }, - { storage = Storage.Quest.U12_40.TheOrderOfTheLion.AccessEastSide, storageValue = 1 }, - { storage = Storage.Quest.U12_40.TheOrderOfTheLion.AccessSouthernSide, storageValue = 1 }, - { storage = Storage.Quest.U12_60.APiratesTail.TentuglyDoor, storageValue = 1 }, - { storage = Storage.Quest.U12_60.APiratesTail.RascacoonShortcut, storageValue = 1 }, - { storage = Storage.Quest.U12_70.AdventuresOfGalthen.AccessDoor, storageValue = 1 }, - - { storage = Storage.CultsOfTibia.Barkless.AccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.TrialAccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.TarAccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Barkless.BossAccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Life.AccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.Misguided.AccessDoor, storageValue = 1 }, - { storage = Storage.CultsOfTibia.FinalBoss.AccessDoor, storageValue = 1 }, - - { storage = Storage.Quest.U10_90.FerumbrasAscension.FirstDoor, storageValue = 1 }, - { storage = Storage.Quest.U10_90.FerumbrasAscension.MonsterDoor, storageValue = 1 }, - { storage = Storage.Quest.U10_90.FerumbrasAscension.TarbazDoor, storageValue = 1 }, - { storage = Storage.Quest.U10_90.FerumbrasAscension.HabitatsAccess, storageValue = 1 }, - { storage = Storage.Quest.U10_90.FerumbrasAscension.TheLordOfTheLiceAccess, storageValue = 1 }, - { storage = Storage.Quest.U10_90.FerumbrasAscension.Statue, storageValue = 1 }, - - { storage = Storage.Quest.U12_00.TheDreamCourts.AndrewDoor, storageValue = 1 }, - - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.AwarnessEmperor, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.BossRoom, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.InnerSanctum, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Rebel, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.SleepingDragon, storageValue = 2 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Wote10, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Zizzle, storageValue = 1 }, - { storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Zlak, storageValue = 1 }, - - { storage = Storage.TheSecretLibrary.FalconBastionAccess, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.LowerBastionAccess, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.UndergroundBastionAccess, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.ShortcutToBastion, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.OberonAccess, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MotaDoor, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.BasinDoor, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.SkullDoor, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.Mota, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MiniBosses.PreceptorLazare, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MiniBosses.GrandCanonDominus, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MiniBosses.GrandChaplainGaunder, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MiniBosses.GrandCommanderSoeren, storageValue = 1 }, - { storage = Storage.TheSecretLibrary.MiniBosses.DazedLeafGolem, storageValue = 1 }, - - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.DoorToLamp, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.DoorToMaridTerritory, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.DoorToLamp, storageValue = 1 }, - { storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.DoorToEfreetTerritory, storageValue = 1 }, - - { storage = Storage.Quest.U12_20.GraveDanger.QuestLine, storageValue = 14 }, - { storage = Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosDoor, storageValue = 1 }, - - { storage = Storage.Quest.U13_10.CradleOfMonsters.Access.Ingol, storageValue = 1 }, - { storage = Storage.Quest.U13_10.CradleOfMonsters.Access.LowerIngol, storageValue = 1 }, - { storage = Storage.Quest.U13_10.CradleOfMonsters.Access.Monster, storageValue = 1 }, - { storage = Storage.Quest.U13_10.CradleOfMonsters.Access.MutatedAbomination, storageValue = 1 }, - { storage = Storage.Quest.U8_54.TheNewFrontier.SnakeHeadTeleport, storageValue = 1 }, - { storage = Storage.Quest.U9_4.LiquidBlackQuest.Visitor, storageValue = 5 }, - { storage = Storage.Quest.U8_4.BloodBrothers.VengothAccess, storageValue = 1 }, - - -- Assassin Outfit quests - { storage = Storage.Quest.U8_5.KillingInTheNameOf.BudrikMinos, storageValue = 0 }, - { storage = Storage.Quest.U8_1.ToOutfoxAFoxQuest.Questline, storageValue = 2 }, - - -- Hunter Outfit quests - { storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet01, storageValue = 1 }, - { storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet02, storageValue = 1 }, - { storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet03, storageValue = 1 }, - { storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet04, storageValue = 1 }, - - -- Norseman - { storage = Storage.Quest.U8_0.TheIceIslands.NorsemanOutfit, storageValue = 1 }, - { storage = Storage.OutfitQuest.DefaultStart, storageValue = 1 }, - - { storage = Storage.HeroRathleton.AccessDoor, storageValue = 1 }, - { storage = Storage.HeroRathleton.AccessTeleport1, storageValue = 1 }, - { storage = Storage.HeroRathleton.AccessTeleport2, storageValue = 1 }, - { storage = Storage.HeroRathleton.AccessTeleport3, storageValue = 1 }, - - -- Sea Serpent Quest - { storage = Storage.Quest.U8_2.TheHuntForTheSeaSerpent.FishForASerpent, storageValue = 5 }, - { storage = Storage.Quest.U8_2.TheHuntForTheSeaSerpent.QuestLine, storageValue = 2 }, - - --The White Raven Monastery - { storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.QuestLog, storageValue = 1 }, - { storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Passage, storageValue = 1 }, - { storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Diary, storageValue = 2 }, - { storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Door, storageValue = 1 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 2 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 4 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 7 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 9 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 12 }, + { storageName = "BigfootsBurden.Shooting", storage = Storage.Quest.U9_60.BigfootsBurden.Shooting, storageValue = 5 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 16 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 20 }, + { storageName = "BigfootsBurden.QuestLine", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLine, storageValue = 23 }, + { storageName = "BigfootsBurden.QuestLineComplete", storage = Storage.Quest.U9_60.BigfootsBurden.QuestLineComplete, storageValue = 2 }, + { storageName = "BigfootsBurden.Rank", storage = Storage.Quest.U9_60.BigfootsBurden.Rank, storageValue = 1440 }, + { storageName = "BigfootsBurden.Warzone1Access", storage = Storage.Quest.U9_60.BigfootsBurden.Warzone1Access, storageValue = 2 }, + { storageName = "BigfootsBurden.Warzone2Access", storage = Storage.Quest.U9_60.BigfootsBurden.Warzone2Access, storageValue = 2 }, + { storageName = "BigfootsBurden.Warzone3Access", storage = Storage.Quest.U9_60.BigfootsBurden.Warzone3Access, storageValue = 2 }, + { storageName = "DangerousDepths.Questline", storage = Storage.Quest.U11_50.DangerousDepths.Questline, storageValue = 10 }, + { storageName = "DangerousDepths.Access.LavaPumpWarzoneVI", storage = Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI, storageValue = 10 }, + { storageName = "DangerousDepths.Access.LavaPumpWarzoneV", storage = Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV, storageValue = 10 }, + { storageName = "DangerousDepths.Access.LavaPumpWarzoneIV", storage = Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV, storageValue = 30 }, + { storageName = "DangerousDepths.Dwarves.Points", storage = Storage.Quest.U11_50.DangerousDepths.Dwarves.Points, storageValue = 10 }, + { storageName = "DangerousDepths.Scouts.Points", storage = Storage.Quest.U11_50.DangerousDepths.Scouts.Points, storageValue = 10 }, + { storageName = "DangerousDepths.Gnomes.Points", storage = Storage.Quest.U11_50.DangerousDepths.Gnomes.Points, storageValue = 10 }, + { storageName = "InServiceOfYalahar.Questline", storage = Storage.Quest.U8_4.InServiceOfYalahar.Questline, storageValue = 51 }, + { storageName = "InServiceOfYalahar.Mission01", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission01, storageValue = 6 }, + { storageName = "InServiceOfYalahar.Mission02", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission02, storageValue = 8 }, + { storageName = "InServiceOfYalahar.Mission03", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission03, storageValue = 6 }, + { storageName = "InServiceOfYalahar.Mission04", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission04, storageValue = 6 }, + { storageName = "InServiceOfYalahar.Mission05", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission05, storageValue = 8 }, + { storageName = "InServiceOfYalahar.Mission06", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission06, storageValue = 5 }, + { storageName = "InServiceOfYalahar.Mission07", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission07, storageValue = 5 }, + { storageName = "InServiceOfYalahar.Mission08", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission08, storageValue = 4 }, + { storageName = "InServiceOfYalahar.Mission09", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission09, storageValue = 2 }, + { storageName = "InServiceOfYalahar.Mission10", storage = Storage.Quest.U8_4.InServiceOfYalahar.Mission10, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SewerPipe01", storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe01, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SewerPipe02", storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe02, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SewerPipe03", storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe03, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SewerPipe04", storage = Storage.Quest.U8_4.InServiceOfYalahar.SewerPipe04, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DiseasedDan", storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedDan, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DiseasedBill", storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedBill, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DiseasedFred", storage = Storage.Quest.U8_4.InServiceOfYalahar.DiseasedFred, storageValue = 1 }, + { storageName = "InServiceOfYalahar.AlchemistFormula", storage = Storage.Quest.U8_4.InServiceOfYalahar.AlchemistFormula, storageValue = 1 }, + { storageName = "InServiceOfYalahar.BadSide", storage = Storage.Quest.U8_4.InServiceOfYalahar.BadSide, storageValue = 1 }, + { storageName = "InServiceOfYalahar.GoodSide", storage = Storage.Quest.U8_4.InServiceOfYalahar.GoodSide, storageValue = 1 }, + { storageName = "InServiceOfYalahar.MrWestDoor", storage = Storage.Quest.U8_4.InServiceOfYalahar.MrWestDoor, storageValue = 1 }, + { storageName = "InServiceOfYalahar.MrWestStatus", storage = Storage.Quest.U8_4.InServiceOfYalahar.MrWestStatus, storageValue = 1 }, + { storageName = "InServiceOfYalahar.TamerinStatus", storage = Storage.Quest.U8_4.InServiceOfYalahar.TamerinStatus, storageValue = 1 }, + { storageName = "InServiceOfYalahar.MorikSummon", storage = Storage.Quest.U8_4.InServiceOfYalahar.MorikSummon, storageValue = 1 }, + { storageName = "InServiceOfYalahar.QuaraState", storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraState, storageValue = 1 }, + { storageName = "InServiceOfYalahar.QuaraSplasher", storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraSplasher, storageValue = 1 }, + { storageName = "InServiceOfYalahar.QuaraSharptooth", storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraSharptooth, storageValue = 1 }, + { storageName = "InServiceOfYalahar.QuaraInky", storage = Storage.Quest.U8_4.InServiceOfYalahar.QuaraInky, storageValue = 1 }, + { storageName = "InServiceOfYalahar.MatrixState", storage = Storage.Quest.U8_4.InServiceOfYalahar.MatrixState, storageValue = 1 }, + { storageName = "InServiceOfYalahar.NotesPalimuth", storage = Storage.Quest.U8_4.InServiceOfYalahar.NotesPalimuth, storageValue = 1 }, + { storageName = "InServiceOfYalahar.NotesAzerus", storage = Storage.Quest.U8_4.InServiceOfYalahar.NotesAzerus, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DoorToAzerus", storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToAzerus, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DoorToBog", storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToBog, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DoorToLastFight", storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToLastFight, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DoorToMatrix", storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToMatrix, storageValue = 1 }, + { storageName = "InServiceOfYalahar.DoorToQuara", storage = Storage.Quest.U8_4.InServiceOfYalahar.DoorToQuara, storageValue = 1 }, + { storageName = "CultsOfTibia.Questline", storage = Storage.Quest.U11_40.CultsOfTibia.Questline, storageValue = 7 }, + { storageName = "CultsOfTibia.Minotaurs.JamesfrancisTask", storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask, storageValue = 1 }, + { storageName = "CultsOfTibia.Minotaurs.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.Minotaurs.BossTimer", storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.BossTimer, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.Stone1", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.Stone2", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.Stone3", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.Answer", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.Answer, storageValue = 1 }, + { storageName = "CultsOfTibia.MotA.QuestionId", storage = Storage.Quest.U11_40.CultsOfTibia.MotA.QuestionId, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.Sulphur", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Sulphur, storageValue = 4 }, + { storageName = "CultsOfTibia.Barkless.Tar", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar, storageValue = 3 }, + { storageName = "CultsOfTibia.Barkless.Ice", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Ice, storageValue = 3 }, + { storageName = "CultsOfTibia.Barkless.Objects", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.Temp", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Temp, storageValue = 1 }, + { storageName = "CultsOfTibia.Orcs.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Orcs.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.Orcs.LookType", storage = Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType, storageValue = 1 }, + { storageName = "CultsOfTibia.Orcs.BossTimer", storage = Storage.Quest.U11_40.CultsOfTibia.Orcs.BossTimer, storageValue = 1 }, + { storageName = "CultsOfTibia.Life.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Life.Mission, storageValue = 7 }, + { storageName = "CultsOfTibia.Life.BossTimer", storage = Storage.Quest.U11_40.CultsOfTibia.Life.BossTimer, storageValue = 1 }, + { storageName = "CultsOfTibia.Humans.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.Humans.Vaporized", storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Vaporized, storageValue = 1 }, + { storageName = "CultsOfTibia.Humans.Decaying", storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Decaying, storageValue = 1 }, + { storageName = "CultsOfTibia.Humans.BossTimer", storage = Storage.Quest.U11_40.CultsOfTibia.Humans.BossTimer, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.Mission", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.Monsters", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.Exorcisms", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Exorcisms, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.Time", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Time, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.BossTimer", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.BossTimer, storageValue = 1 }, + { storageName = "CultsOfTibia.Minotaurs.BossAccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.BossAccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Minotaurs.AccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.AccessDoor, storageValue = 1 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 1 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 4 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 7 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 16 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 26 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 29 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 32 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 35 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 38 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 41 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 43 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 46 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 47 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 50 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 55 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 56 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 58 }, + { storageName = "ExplorerSociety.QuestLine", storage = Storage.Quest.U7_6.ExplorerSociety.QuestLine, storageValue = 61 }, + { storageName = "ExplorerSociety.CalassaQuest", storage = Storage.Quest.U7_6.ExplorerSociety.CalassaQuest, storageValue = 2 }, + { storageName = "ForgottenKnowledge.Tomes", storage = Storage.Quest.U11_02.ForgottenKnowledge.Tomes, storageValue = 1 }, + { storageName = "ForgottenKnowledge.LastLoreKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.LastLoreKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.TimeGuardianKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.HorrorKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.HorrorKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.DragonkingKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.DragonkingKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.ThornKnightKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.ThornKnightKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.LloydKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.LloydKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.LadyTenebrisKilled", storage = Storage.Quest.U11_02.ForgottenKnowledge.LadyTenebrisKilled, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessMachine", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessMachine, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessLavaTeleport", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessLavaTeleport, storageValue = 1 }, + { storageName = "BarbarianTest.Questline", storage = Storage.Quest.U8_0.BarbarianTest.Questline, storageValue = 8 }, + { storageName = "BarbarianTest.Mission01", storage = Storage.Quest.U8_0.BarbarianTest.Mission01, storageValue = 3 }, + { storageName = "BarbarianTest.Mission02", storage = Storage.Quest.U8_0.BarbarianTest.Mission02, storageValue = 3 }, + { storageName = "BarbarianTest.Mission03", storage = Storage.Quest.U8_0.BarbarianTest.Mission03, storageValue = 3 }, + { storageName = "ChildrenOfTheRevolution.Questline", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Questline, storageValue = 21 }, + { storageName = "ChildrenOfTheRevolution.Mission00", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission00, storageValue = 2 }, + { storageName = "ChildrenOfTheRevolution.Mission01", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission01, storageValue = 3 }, + { storageName = "ChildrenOfTheRevolution.Mission02", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission02, storageValue = 5 }, + { storageName = "ChildrenOfTheRevolution.Mission03", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission03, storageValue = 3 }, + { storageName = "ChildrenOfTheRevolution.Mission04", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission04, storageValue = 6 }, + { storageName = "ChildrenOfTheRevolution.Mission05", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.Mission05, storageValue = 3 }, + { storageName = "ChildrenOfTheRevolution.SpyBuilding01", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding01, storageValue = 1 }, + { storageName = "ChildrenOfTheRevolution.SpyBuilding02", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding02, storageValue = 1 }, + { storageName = "ChildrenOfTheRevolution.SpyBuilding03", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.SpyBuilding03, storageValue = 1 }, + { storageName = "ChildrenOfTheRevolution.StrangeSymbols", storage = Storage.Quest.U8_54.ChildrenOfTheRevolution.StrangeSymbols, storageValue = 1 }, + { storageName = "DjinnWar.Faction.Greeting", storage = Storage.Quest.U7_4.DjinnWar.Faction.Greeting, storageValue = 2 }, + { storageName = "DjinnWar.Faction.MaridDoor", storage = Storage.Quest.U7_4.DjinnWar.Faction.MaridDoor, storageValue = 2 }, + { storageName = "DjinnWar.Faction.EfreetDoor", storage = Storage.Quest.U7_4.DjinnWar.Faction.EfreetDoor, storageValue = 2 }, + { storageName = "DjinnWar.EfreetFaction.Start", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Start, storageValue = 1 }, + { storageName = "DjinnWar.EfreetFaction.Mission01", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission01, storageValue = 3 }, + { storageName = "DjinnWar.EfreetFaction.Mission02", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission02, storageValue = 3 }, + { storageName = "DjinnWar.EfreetFaction.Mission03", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.Mission03, storageValue = 3 }, + { storageName = "DjinnWar.MaridFaction.Start", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Start, storageValue = 1 }, + { storageName = "DjinnWar.MaridFaction.Mission01", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission01, storageValue = 2 }, + { storageName = "DjinnWar.MaridFaction.Mission02", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission02, storageValue = 2 }, + { storageName = "DjinnWar.MaridFaction.RataMari", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.RataMari, storageValue = 2 }, + { storageName = "DjinnWar.MaridFaction.Mission03", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.Mission03, storageValue = 3 }, + { storageName = "InServiceOfYalahar.TheWayToYalahar", storage = Storage.Quest.U8_4.InServiceOfYalahar.TheWayToYalahar, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.TownsCounter", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.TownsCounter, storageValue = 5 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.AbDendriel", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.AbDendriel, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.Darashia", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Darashia, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.Venore", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Venore, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.Ankrahmun", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Ankrahmun, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.PortHope", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.PortHope, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.Thais", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Thais, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.LibertyBay", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.LibertyBay, storageValue = 1 }, + { storageName = "InServiceOfYalahar.SearoutesAroundYalahar.Carlin", storage = Storage.Quest.U8_4.InServiceOfYalahar.SearoutesAroundYalahar.Carlin, storageValue = 1 }, + { storageName = "TheHiddenCityOfBeregar.DefaultStart", storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.DefaultStart, storageValue = 1 }, + { storageName = "TheHiddenCityOfBeregar.GoingDown", storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.GoingDown, storageValue = 1 }, + { storageName = "TheHiddenCityOfBeregar.WayToBeregar", storage = Storage.Quest.U8_4.TheHiddenCityOfBeregar.WayToBeregar, storageValue = 1 }, + { storageName = "TheIceIslands.Questline", storage = Storage.Quest.U8_0.TheIceIslands.Questline, storageValue = 40 }, + { storageName = "TheIceIslands.Mission01", storage = Storage.Quest.U8_0.TheIceIslands.Mission01, storageValue = 3 }, + { storageName = "TheIceIslands.Mission02", storage = Storage.Quest.U8_0.TheIceIslands.Mission02, storageValue = 5 }, + { storageName = "TheIceIslands.Mission03", storage = Storage.Quest.U8_0.TheIceIslands.Mission03, storageValue = 3 }, + { storageName = "TheIceIslands.Mission04", storage = Storage.Quest.U8_0.TheIceIslands.Mission04, storageValue = 2 }, + { storageName = "TheIceIslands.Mission05", storage = Storage.Quest.U8_0.TheIceIslands.Mission05, storageValue = 6 }, + { storageName = "TheIceIslands.Mission06", storage = Storage.Quest.U8_0.TheIceIslands.Mission06, storageValue = 8 }, + { storageName = "TheIceIslands.Mission07", storage = Storage.Quest.U8_0.TheIceIslands.Mission07, storageValue = 3 }, + { storageName = "TheIceIslands.Mission08", storage = Storage.Quest.U8_0.TheIceIslands.Mission08, storageValue = 4 }, + { storageName = "TheIceIslands.Mission09", storage = Storage.Quest.U8_0.TheIceIslands.Mission09, storageValue = 2 }, + { storageName = "TheIceIslands.Mission10", storage = Storage.Quest.U8_0.TheIceIslands.Mission10, storageValue = 2 }, + { storageName = "TheIceIslands.Mission11", storage = Storage.Quest.U8_0.TheIceIslands.Mission11, storageValue = 2 }, + { storageName = "TheIceIslands.Mission12", storage = Storage.Quest.U8_0.TheIceIslands.Mission12, storageValue = 6 }, + { storageName = "TheIceIslands.yakchalDoor", storage = Storage.Quest.U8_0.TheIceIslands.yakchalDoor, storageValue = 1 }, + { storageName = "TheInquisitionQuest.Questline", storage = Storage.Quest.U8_2.TheInquisitionQuest.Questline, storageValue = 25 }, + { storageName = "TheInquisitionQuest.Mission01", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission01, storageValue = 7 }, + { storageName = "TheInquisitionQuest.Mission02", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission02, storageValue = 3 }, + { storageName = "TheInquisitionQuest.Mission03", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission03, storageValue = 6 }, + { storageName = "TheInquisitionQuest.Mission04", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission04, storageValue = 3 }, + { storageName = "TheInquisitionQuest.Mission05", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission05, storageValue = 3 }, + { storageName = "TheInquisitionQuest.Mission06", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission06, storageValue = 3 }, + { storageName = "TheInquisitionQuest.Mission07", storage = Storage.Quest.U8_2.TheInquisitionQuest.Mission07, storageValue = 1 }, + { storageName = "TheInquisitionQuest.GrofGuard", storage = Storage.Quest.U8_2.TheInquisitionQuest.GrofGuard, storageValue = 1 }, + { storageName = "TheInquisitionQuest.KulagGuard", storage = Storage.Quest.U8_2.TheInquisitionQuest.KulagGuard, storageValue = 1 }, + { storageName = "TheInquisitionQuest.TimGuard", storage = Storage.Quest.U8_2.TheInquisitionQuest.TimGuard, storageValue = 1 }, + { storageName = "TheInquisitionQuest.WalterGuard", storage = Storage.Quest.U8_2.TheInquisitionQuest.WalterGuard, storageValue = 1 }, + { storageName = "TheInquisitionQuest.StorkusVampiredust", storage = Storage.Quest.U8_2.TheInquisitionQuest.StorkusVampiredust, storageValue = 1 }, + { storageName = "TheNewFrontier.Questline", storage = Storage.Quest.U8_54.TheNewFrontier.Questline, storageValue = 29 }, + { storageName = "TheNewFrontier.Mission01", storage = Storage.Quest.U8_54.TheNewFrontier.Mission01, storageValue = 3 }, + { storageName = "TheNewFrontier.Mission02[1]", storage = Storage.Quest.U8_54.TheNewFrontier.Mission02[1], storageValue = 4 }, + { storageName = "TheNewFrontier.Mission03", storage = Storage.Quest.U8_54.TheNewFrontier.Mission03, storageValue = 3 }, + { storageName = "TheNewFrontier.Mission04", storage = Storage.Quest.U8_54.TheNewFrontier.Mission04, storageValue = 2 }, + { storageName = "TheNewFrontier.Mission05[1]", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05[1], storageValue = 2 }, + { storageName = "TheNewFrontier.Mission06", storage = Storage.Quest.U8_54.TheNewFrontier.Mission06, storageValue = 5 }, + { storageName = "TheNewFrontier.Mission07[1]", storage = Storage.Quest.U8_54.TheNewFrontier.Mission07[1], storageValue = 2 }, + { storageName = "TheNewFrontier.Mission08", storage = Storage.Quest.U8_54.TheNewFrontier.Mission08, storageValue = 2 }, + { storageName = "TheNewFrontier.Mission09[1]", storage = Storage.Quest.U8_54.TheNewFrontier.Mission09[1], storageValue = 3 }, + { storageName = "TheNewFrontier.Mission10[1]", storage = Storage.Quest.U8_54.TheNewFrontier.Mission10[1], storageValue = 2 }, + { storageName = "TheNewFrontier.Mission10.MagicCarpetDoor", storage = Storage.Quest.U8_54.TheNewFrontier.Mission10.MagicCarpetDoor, storageValue = 1 }, + { storageName = "TheNewFrontier.TomeofKnowledge", storage = Storage.Quest.U8_54.TheNewFrontier.TomeofKnowledge, storageValue = 12 }, + { storageName = "TheNewFrontier.Mission02.Beaver1", storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver1, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission02.Beaver2", storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver2, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission02.Beaver3", storage = Storage.Quest.U8_54.TheNewFrontier.Mission02.Beaver3, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.KingTibianus", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.KingTibianus, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.Leeland", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Leeland, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.Angus", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Angus, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.Wyrdin", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Wyrdin, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.Telas", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Telas, storageValue = 1 }, + { storageName = "TheNewFrontier.Mission05.Humgolf", storage = Storage.Quest.U8_54.TheNewFrontier.Mission05.Humgolf, storageValue = 1 }, + { storageName = "TheShatteredIsles.DefaultStart", storage = Storage.Quest.U7_8.TheShatteredIsles.DefaultStart, storageValue = 3 }, + { storageName = "TheShatteredIsles.TheGovernorDaughter", storage = Storage.Quest.U7_8.TheShatteredIsles.TheGovernorDaughter, storageValue = 3 }, + { storageName = "TheShatteredIsles.TheErrand", storage = Storage.Quest.U7_8.TheShatteredIsles.TheErrand, storageValue = 2 }, + { storageName = "TheShatteredIsles.AccessToMeriana", storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToMeriana, storageValue = 1 }, + { storageName = "TheShatteredIsles.APoemForTheMermaid", storage = Storage.Quest.U7_8.TheShatteredIsles.APoemForTheMermaid, storageValue = 3 }, + { storageName = "TheShatteredIsles.ADjinnInLove", storage = Storage.Quest.U7_8.TheShatteredIsles.ADjinnInLove, storageValue = 5 }, + { storageName = "TheShatteredIsles.AccessToLagunaIsland", storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToLagunaIsland, storageValue = 1 }, + { storageName = "TheShatteredIsles.AccessToGoroma", storage = Storage.Quest.U7_8.TheShatteredIsles.AccessToGoroma, storageValue = 1 }, + { storageName = "TheShatteredIsles.Shipwrecked", storage = Storage.Quest.U7_8.TheShatteredIsles.Shipwrecked, storageValue = 2 }, + { storageName = "TheShatteredIsles.DragahsSpellbook", storage = Storage.Quest.U7_8.TheShatteredIsles.DragahsSpellbook, storageValue = 1 }, + { storageName = "TheShatteredIsles.TheCounterspell", storage = Storage.Quest.U7_8.TheShatteredIsles.TheCounterspell, storageValue = 4 }, + { storageName = "TheThievesGuildQuest.Questline", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Questline, storageValue = 1 }, + { storageName = "TheThievesGuildQuest.Mission01", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission01, storageValue = 2 }, + { storageName = "TheThievesGuildQuest.Mission02", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission02, storageValue = 3 }, + { storageName = "TheThievesGuildQuest.Mission03", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission03, storageValue = 3 }, + { storageName = "TheThievesGuildQuest.Mission04", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission04, storageValue = 8 }, + { storageName = "TheThievesGuildQuest.Mission05", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission05, storageValue = 2 }, + { storageName = "TheThievesGuildQuest.Mission06", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission06, storageValue = 4 }, + { storageName = "TheThievesGuildQuest.Mission07", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission07, storageValue = 2 }, + { storageName = "TheThievesGuildQuest.Mission08", storage = Storage.Quest.U8_2.TheThievesGuildQuest.Mission08, storageValue = 1 }, + { storageName = "TheTravellingTrader.Mission01", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission01, storageValue = 1 }, + { storageName = "TheTravellingTrader.Mission01_2", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission01, storageValue = 2 }, + { storageName = "TheTravellingTrader.Mission02", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission02, storageValue = 5 }, + { storageName = "TheTravellingTrader.Mission03", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission03, storageValue = 3 }, + { storageName = "TheTravellingTrader.Mission04", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission04, storageValue = 3 }, + { storageName = "TheTravellingTrader.Mission05", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission05, storageValue = 3 }, + { storageName = "TheTravellingTrader.Mission06", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission06, storageValue = 2 }, + { storageName = "TheTravellingTrader.Mission07", storage = Storage.Quest.U8_1.TheTravellingTrader.Mission07, storageValue = 1 }, + { storageName = "BarbarianArena.QuestLogGreenhorn", storage = Storage.Quest.U8_0.BarbarianArena.QuestLogGreenhorn, storageValue = 1 }, + { storageName = "TibiaTales.DefaultStart", storage = Storage.Quest.U8_1.TibiaTales.DefaultStart, storageValue = 1 }, + { storageName = "TibiaTales.ToAppeaseTheMightyQuest", storage = Storage.Quest.U8_1.TibiaTales.ToAppeaseTheMightyQuest, storageValue = 1 }, + { storageName = "12450", storage = 12450, storageValue = 6 }, + { storageName = "12330", storage = 12330, storageValue = 1 }, + { storageName = "12332", storage = 12332, storageValue = 13 }, + { storageName = "12333", storage = 12333, storageValue = 3 }, + { storageName = "FriendsAndTraders.DefaultStart", storage = Storage.Quest.U7_8.FriendsAndTraders.DefaultStart, storageValue = 1 }, + { storageName = "FriendsAndTraders.TheSweatyCyclops", storage = Storage.Quest.U7_8.FriendsAndTraders.TheSweatyCyclops, storageValue = 2 }, + { storageName = "FriendsAndTraders.TheMermaidMarina", storage = Storage.Quest.U7_8.FriendsAndTraders.TheMermaidMarina, storageValue = 2 }, + { storageName = "FriendsAndTraders.TheBlessedStake", storage = Storage.Quest.U7_8.FriendsAndTraders.TheBlessedStake, storageValue = 12 }, + { storageName = "100157", storage = 100157, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.Questline", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Questline, storageValue = 29 }, + { storageName = "WrathOfTheEmperor.Mission01", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission01, storageValue = 3 }, + { storageName = "WrathOfTheEmperor.Mission02", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission02, storageValue = 3 }, + { storageName = "WrathOfTheEmperor.Mission03", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission03, storageValue = 3 }, + { storageName = "WrathOfTheEmperor.Mission04", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission04, storageValue = 3 }, + { storageName = "WrathOfTheEmperor.Mission05", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission05, storageValue = 3 }, + { storageName = "WrathOfTheEmperor.Mission06", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission06, storageValue = 4 }, + { storageName = "WrathOfTheEmperor.Mission07", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission07, storageValue = 6 }, + { storageName = "WrathOfTheEmperor.Mission08", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission08, storageValue = 2 }, + { storageName = "WrathOfTheEmperor.Mission09", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission09, storageValue = 2 }, + { storageName = "WrathOfTheEmperor.Mission10", storage = Storage.Quest.U8_6.WrathOfTheEmperor.Mission10, storageValue = 1 }, + { storageName = "TheApeCity.Started", storage = Storage.Quest.U7_6.TheApeCity.Started, storageValue = 1 }, + { storageName = "TheApeCity.Questline", storage = Storage.Quest.U7_6.TheApeCity.Questline, storageValue = 18 }, + { storageName = "BanutaSecretTunnel.DeeperBanutaShortcut", storage = Storage.BanutaSecretTunnel.DeeperBanutaShortcut, storageValue = 1 }, + { storageName = "OramondQuest.QuestLine", storage = Storage.Quest.U10_50.OramondQuest.QuestLine, storageValue = 1 }, + { storageName = "OramondQuest.ToTakeRoots.Mission", storage = Storage.Quest.U10_50.OramondQuest.ToTakeRoots.Mission, storageValue = 3000 }, + { storageName = "DangerousDepths.Questline", storage = Storage.Quest.U11_50.DangerousDepths.Questline, storageValue = 1 }, + { storageName = "DangerousDepths.Dwarves.Home", storage = Storage.Quest.U11_50.DangerousDepths.Dwarves.Home, storageValue = 2 }, + { storageName = "DangerousDepths.Dwarves.Subterranean", storage = Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean, storageValue = 2 }, + { storageName = "DangerousDepths.Gnomes.Measurements", storage = Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements, storageValue = 2 }, + { storageName = "DangerousDepths.Gnomes.Ordnance", storage = Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, storageValue = 3 }, + { storageName = "DangerousDepths.Gnomes.Charting", storage = Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting, storageValue = 2 }, + { storageName = "DangerousDepths.Scouts.Growth", storage = Storage.Quest.U11_50.DangerousDepths.Scouts.Growth, storageValue = 2 }, + { storageName = "DangerousDepths.Scouts.Diremaw", storage = Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw, storageValue = 2 }, + { storageName = "ThreatenedDreams.QuestLine", storage = Storage.Quest.U11_40.ThreatenedDreams.QuestLine, storageValue = 1 }, + { storageName = "ThreatenedDreams.Mission01[1]", storage = Storage.Quest.U11_40.ThreatenedDreams.Mission01[1], storageValue = 16 }, + { storageName = "ThreatenedDreams.Mission02.KroazurAccess", storage = Storage.Quest.U11_40.ThreatenedDreams.Mission02.KroazurAccess, storageValue = 1 }, + { storageName = "AdventurersGuild.QuestLine", storage = Storage.Quest.U9_80.AdventurersGuild.QuestLine, storageValue = 1 }, + { storageName = "TheGreatDragonHunt.WarriorSkeleton", storage = Storage.Quest.U10_80.TheGreatDragonHunt.WarriorSkeleton, storageValue = 1 }, + { storageName = "TheGreatDragonHunt.WarriorSkeleton_2", storage = Storage.Quest.U10_80.TheGreatDragonHunt.WarriorSkeleton, storageValue = 2 }, + { storageName = "TheLostBrotherQuest", storage = Storage.Quest.U10_80.TheLostBrotherQuest, storageValue = 3 }, + { storageName = "Dawnport.Questline", storage = Storage.Quest.U10_55.Dawnport.Questline, storageValue = 1 }, + { storageName = "Dawnport.GoMain", storage = Storage.Quest.U10_55.Dawnport.GoMain, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessDeath", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessDeath, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessViolet", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessViolet, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessEarth", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessEarth, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessFire", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessFire, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessIce", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessIce, storageValue = 1 }, + { storageName = "ForgottenKnowledge.AccessGolden", storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessGolden, storageValue = 1 }, + { storageName = "GrimvaleQuest.AncientFeudDoors", storage = Storage.Quest.U10_80.GrimvaleQuest.AncientFeudDoors, storageValue = 1 }, + { storageName = "GrimvaleQuest.AncientFeudShortcut", storage = Storage.Quest.U10_80.GrimvaleQuest.AncientFeudShortcut, storageValue = 1 }, + { storageName = "Kilmaresh.AccessDoor", storage = Storage.Kilmaresh.AccessDoor, storageValue = 1 }, + { storageName = "Kilmaresh.CatacombDoors", storage = Storage.Kilmaresh.CatacombDoors, storageValue = 1 }, + { storageName = "TheOrderOfTheLion.AccessEastSide", storage = Storage.Quest.U12_40.TheOrderOfTheLion.AccessEastSide, storageValue = 1 }, + { storageName = "TheOrderOfTheLion.AccessSouthernSide", storage = Storage.Quest.U12_40.TheOrderOfTheLion.AccessSouthernSide, storageValue = 1 }, + { storageName = "APiratesTail.TentuglyDoor", storage = Storage.Quest.U12_60.APiratesTail.TentuglyDoor, storageValue = 1 }, + { storageName = "APiratesTail.RascacoonShortcut", storage = Storage.Quest.U12_60.APiratesTail.RascacoonShortcut, storageValue = 1 }, + { storageName = "AdventuresOfGalthen.AccessDoor", storage = Storage.Quest.U12_70.AdventuresOfGalthen.AccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.AccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.AccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.TrialAccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.TrialAccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.TarAccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.TarAccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Barkless.BossAccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.BossAccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Life.AccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Life.AccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.Misguided.AccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.AccessDoor, storageValue = 1 }, + { storageName = "CultsOfTibia.FinalBoss.AccessDoor", storage = Storage.Quest.U11_40.CultsOfTibia.FinalBoss.AccessDoor, storageValue = 1 }, + { storageName = "FerumbrasAscension.FirstDoor", storage = Storage.Quest.U10_90.FerumbrasAscension.FirstDoor, storageValue = 1 }, + { storageName = "FerumbrasAscension.MonsterDoor", storage = Storage.Quest.U10_90.FerumbrasAscension.MonsterDoor, storageValue = 1 }, + { storageName = "FerumbrasAscension.TarbazDoor", storage = Storage.Quest.U10_90.FerumbrasAscension.TarbazDoor, storageValue = 1 }, + { storageName = "FerumbrasAscension.HabitatsAccess", storage = Storage.Quest.U10_90.FerumbrasAscension.HabitatsAccess, storageValue = 1 }, + { storageName = "FerumbrasAscension.TheLordOfTheLiceAccess", storage = Storage.Quest.U10_90.FerumbrasAscension.TheLordOfTheLiceAccess, storageValue = 1 }, + { storageName = "FerumbrasAscension.Statue", storage = Storage.Quest.U10_90.FerumbrasAscension.Statue, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.AwarnessEmperor", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.AwarnessEmperor, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.BossRoom", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.BossRoom, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.InnerSanctum", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.InnerSanctum, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.Rebel", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Rebel, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.SleepingDragon", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.SleepingDragon, storageValue = 2 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.Wote10", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Wote10, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.Zizzle", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Zizzle, storageValue = 1 }, + { storageName = "WrathOfTheEmperor.TeleportAccess.Zlak", storage = Storage.Quest.U8_6.WrathOfTheEmperor.TeleportAccess.Zlak, storageValue = 1 }, + { storageName = "DjinnWar.EfreetFaction.DoorToLamp", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.DoorToLamp, storageValue = 1 }, + { storageName = "DjinnWar.EfreetFaction.DoorToMaridTerritory", storage = Storage.Quest.U7_4.DjinnWar.EfreetFaction.DoorToMaridTerritory, storageValue = 1 }, + { storageName = "DjinnWar.MaridFaction.DoorToLamp", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.DoorToLamp, storageValue = 1 }, + { storageName = "DjinnWar.MaridFaction.DoorToEfreetTerritory", storage = Storage.Quest.U7_4.DjinnWar.MaridFaction.DoorToEfreetTerritory, storageValue = 1 }, + { storageName = "GraveDanger.QuestLine", storage = Storage.Quest.U12_20.GraveDanger.QuestLine, storageValue = 14 }, + { storageName = "GraveDanger.Bosses.KingZelosDoor", storage = Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosDoor, storageValue = 1 }, + { storageName = "CradleOfMonsters.Access.Ingol", storage = Storage.Quest.U13_10.CradleOfMonsters.Access.Ingol, storageValue = 1 }, + { storageName = "CradleOfMonsters.Access.LowerIngol", storage = Storage.Quest.U13_10.CradleOfMonsters.Access.LowerIngol, storageValue = 1 }, + { storageName = "CradleOfMonsters.Access.Monster", storage = Storage.Quest.U13_10.CradleOfMonsters.Access.Monster, storageValue = 1 }, + { storageName = "CradleOfMonsters.Access.MutatedAbomination", storage = Storage.Quest.U13_10.CradleOfMonsters.Access.MutatedAbomination, storageValue = 1 }, + { storageName = "TheNewFrontier.SnakeHeadTeleport", storage = Storage.Quest.U8_54.TheNewFrontier.SnakeHeadTeleport, storageValue = 1 }, + { storageName = "LiquidBlackQuest.Visitor", storage = Storage.Quest.U9_4.LiquidBlackQuest.Visitor, storageValue = 5 }, + { storageName = "BloodBrothers.VengothAccess", storage = Storage.Quest.U8_4.BloodBrothers.VengothAccess, storageValue = 1 }, + { storageName = "KillingInTheNameOf.BudrikMinos", storage = Storage.Quest.U8_5.KillingInTheNameOf.BudrikMinos, storageValue = 0 }, + { storageName = "ToOutfoxAFoxQuest.Questline", storage = Storage.Quest.U8_1.ToOutfoxAFoxQuest.Questline, storageValue = 2 }, + { storageName = "HunterOutfits.HunterMusicSheet01", storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet01, storageValue = 1 }, + { storageName = "HunterOutfits.HunterMusicSheet02", storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet02, storageValue = 1 }, + { storageName = "HunterOutfits.HunterMusicSheet03", storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet03, storageValue = 1 }, + { storageName = "HunterOutfits.HunterMusicSheet04", storage = Storage.Quest.U7_8.HunterOutfits.HunterMusicSheet04, storageValue = 1 }, + { storageName = "TheIceIslands.NorsemanOutfit", storage = Storage.Quest.U8_0.TheIceIslands.NorsemanOutfit, storageValue = 1 }, + { storageName = "OutfitQuest.DefaultStart", storage = Storage.OutfitQuest.DefaultStart, storageValue = 1 }, + { storageName = "HeroRathleton.AccessDoor", storage = Storage.HeroRathleton.AccessDoor, storageValue = 1 }, + { storageName = "HeroRathleton.AccessTeleport1", storage = Storage.HeroRathleton.AccessTeleport1, storageValue = 1 }, + { storageName = "HeroRathleton.AccessTeleport2", storage = Storage.HeroRathleton.AccessTeleport2, storageValue = 1 }, + { storageName = "HeroRathleton.AccessTeleport3", storage = Storage.HeroRathleton.AccessTeleport3, storageValue = 1 }, + { storageName = "TheHuntForTheSeaSerpent.FishForASerpent", storage = Storage.Quest.U8_2.TheHuntForTheSeaSerpent.FishForASerpent, storageValue = 5 }, + { storageName = "TheHuntForTheSeaSerpent.QuestLine", storage = Storage.Quest.U8_2.TheHuntForTheSeaSerpent.QuestLine, storageValue = 2 }, + { storageName = "TheWhiteRavenMonastery.QuestLog", storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.QuestLog, storageValue = 1 }, + { storageName = "TheWhiteRavenMonastery.Passage", storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Passage, storageValue = 1 }, + { storageName = "TheWhiteRavenMonastery.Diary", storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Diary, storageValue = 2 }, + { storageName = "TheWhiteRavenMonastery.Door", storage = Storage.Quest.U7_24.TheWhiteRavenMonastery.Door, storageValue = 1 }, } -- from Position: (33201, 31762, 1) @@ -405,8 +367,15 @@ local function playerFreeQuestStart(playerId, index) return end - if player:getStorageValue(questTable[index].storage) ~= questTable[index].storageValue then - player:setStorageValue(questTable[index].storage, questTable[index].storageValue) + local questData = questTable[index] + local currentStorageValue = player:getStorageValue(questData.storage) + + if not questData.storage then + logger.warn("[Freequest System]: error storage for '" .. questData.storageName .. "' is nil for the index") + elseif currentStorageValue ~= questData.storageValue then + player:setStorageValue(questData.storage, questData.storageValue) + elseif currentStorageValue == -1 then + logger.warn("[Freequest System]: warning Storage '" .. questData.storageName .. "' currently nil for player ID " .. playerId) end end diff --git a/data-otservbr-global/scripts/creaturescripts/others/#modal_window_example.lua b/data-otservbr-global/scripts/creaturescripts/others/#modal_window_example.lua deleted file mode 100644 index e2de4a9e474..00000000000 --- a/data-otservbr-global/scripts/creaturescripts/others/#modal_window_example.lua +++ /dev/null @@ -1,63 +0,0 @@ ---[[ - ModalWindowHelper Example -]] --- - -local moveDirectionTest = { - ["Right"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_EAST) - player:teleportTo(pos, true) - end, - ["Left"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_WEST) - player:teleportTo(pos, true) - end, - ["Up"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_NORTH) - player:teleportTo(pos, true) - end, - ["Down"] = function(player) - local pos = player:getPosition() - pos:getNextPosition(DIRECTION_SOUTH) - player:teleportTo(pos, true) - end, -} - -local talkAction = TalkAction("!modalTest") - -function talkAction.onSay(player, words, param, type) - local modalWindow = ModalWindow({ - title = "Modal Window Helper Example", - message = "This is an example of ModalWindowHelper.", - }) - if param == "choices" then - for text, callback in pairs(moveDirectionTest) do - modalWindow:addChoice(text, function(player, button, choice) - if button.name == "Select" then - callback(player) - modalWindow:sendToPlayer(player) - end - end) - end - - modalWindow:addButton("Select") - modalWindow:addButton("Cancel") - elseif param == "buttons" then - for direction, callback in pairs(moveDirectionTest) do - modalWindow:addButton(direction, function(player, button, choice) - callback(player) - modalWindow:sendToPlayer(player) - end) - end - end - modalWindow:sendToPlayer(player) - return false -end - ---talkAction:accountType(ACCOUNT_TYPE_GOD) ---talkAction:access(true) -talkAction:separator(" ") -talkAction:register() diff --git a/data-otservbr-global/scripts/creaturescripts/others/droploot.lua b/data-otservbr-global/scripts/creaturescripts/others/droploot.lua index 7be3564048d..9bf77afa71b 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/droploot.lua +++ b/data-otservbr-global/scripts/creaturescripts/others/droploot.lua @@ -1,5 +1,7 @@ -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") + local dropLoot = CreatureEvent("DropLoot") + function dropLoot.onDeath(player, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) local town = player:getTown() if town and town:getId() == TOWNS_LIST.DAWNPORT and player:getLevel() < 8 then @@ -9,6 +11,7 @@ function dropLoot.onDeath(player, corpse, killer, mostDamage, unjustified, mostD if player:hasFlag(PlayerFlag_NotGenerateLoot) then return true end + Blessings.DebugPrint("onDeath DROPLOOT EVENT DropLoot") return Blessings.PlayerDeath(player, corpse, killer) end diff --git a/data-otservbr-global/scripts/creaturescripts/others/login.lua b/data-otservbr-global/scripts/creaturescripts/others/login.lua index 8457209e90a..c833dfd90fb 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/login.lua +++ b/data-otservbr-global/scripts/creaturescripts/others/login.lua @@ -12,18 +12,18 @@ function playerLogin.onLogin(player) town = table.contains(freeTowns, town:getName()) and town or Town(defaultTown) player:teleportTo(town:getTemplePosition()) player:setTown(town) - player:sendTextMessage(MESSAGE_FAILURE, "Your premium time has expired.") + player:sendTextMessage(MESSAGE_FAILURE, "Your premium time has expired!") if sex == 1 then - player:setOutfit({ lookType = 128, lookFeet = 114, lookLegs = 134, lookHead = 114, lookAddons = 0 }) + player:setOutfit({ lookType = 128, lookHead = 114, lookBody = 120, lookLegs = 132, lookFeet = 115, lookAddons = 0 }) elseif sex == 0 then - player:setOutfit({ lookType = 136, lookFeet = 114, lookLegs = 134, lookHead = 114, lookAddons = 0 }) + player:setOutfit({ lookType = 136, lookHead = 114, lookBody = 120, lookLegs = 132, lookFeet = 115, lookAddons = 0 }) end if home and not player:isPremium() then setHouseOwner(home, 0) - player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "You've lost your house because you are not premium anymore.") - player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "Your items from house are send to your inbox.") + player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "You have lost your house because you are no longer a premium account.") + player:sendTextMessage(MESSAGE_GAME_HIGHLIGHT, "Your items from the house have been sent to your inbox.") end end diff --git a/data-otservbr-global/scripts/globalevents/others/guild_war.lua b/data-otservbr-global/scripts/globalevents/others/guild_war.lua deleted file mode 100644 index 41238755494..00000000000 --- a/data-otservbr-global/scripts/globalevents/others/guild_war.lua +++ /dev/null @@ -1,10 +0,0 @@ -local guildWar = GlobalEvent("guildwar") - -function guildWar.onThink(interval) - local time = os.time() - db.query("UPDATE `guild_wars` SET `status` = 4, `ended` = " .. time .. " WHERE `status` = 1 AND `ended` != 0 AND `ended` < " .. time) - return true -end - -guildWar:interval(60000) -guildWar:register() diff --git a/data-otservbr-global/scripts/lib/monster_functions.lua b/data-otservbr-global/scripts/lib/monster_functions.lua new file mode 100644 index 00000000000..0b362de27a9 --- /dev/null +++ b/data-otservbr-global/scripts/lib/monster_functions.lua @@ -0,0 +1,8 @@ +function Monster:handleCobraOnSpawn() + if Game.getStorageValue(Global.Storage.CobraFlask) >= os.time() then + self:setHealth(self:getMaxHealth() * 0.75) + self:getPosition():sendMagicEffect(CONST_ME_GREEN_RINGS) + else + Game.setStorageValue(Global.Storage.CobraFlask, -1) + end +end diff --git a/data-otservbr-global/scripts/lib/register_actions.lua b/data-otservbr-global/scripts/lib/register_actions.lua index ebb77654882..a65de89e017 100644 --- a/data-otservbr-global/scripts/lib/register_actions.lua +++ b/data-otservbr-global/scripts/lib/register_actions.lua @@ -58,6 +58,22 @@ local lava = { Position(32813, 32333, 11), } +local secret_library = { + crystals = { + [1] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal1, position = Position(33216, 32108, 9) }, + [2] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal2, position = Position(33242, 32100, 9) }, + [3] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal3, position = Position(33226, 32103, 9) }, + [4] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal4, position = Position(33236, 32084, 9) }, + [5] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal5, position = Position(33260, 32103, 9) }, + [6] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal6, position = Position(33260, 32103, 9) }, + [7] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal7, position = Position(33260, 32103, 9) }, + [8] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Crystal8, position = Position(33260, 32103, 9) }, + }, + timer = "tsl_crystaltimer", + exhaustMessage = "Digging crystal is exhausting. You're still weary from your last prospect.", + items = { 27867, 27868, 27869 }, +} + local function revertItem(position, itemId, transformId) local item = Tile(position):getItemById(itemId) if item then @@ -504,6 +520,23 @@ function onUsePick(player, item, fromPosition, target, toPosition, isHotkey) end end + -- The Secret Library Quest + local tPos = toPosition + for _, j in pairs(secret_library.crystals) do + if tPos == j.position then + if player:getStorageValue(j.storage) < os.time() then + local r = math.random(1, 3) + local item_id = secret_library.items[r] + player:addItem(item_id, 1) + player:say("You have found a " .. ItemType(item_id):getName() .. ".", TALKTYPE_MONSTER_SAY) + player:setStorageValue(j.storage, os.time() + 2 * 60) + else + player:say(secret_library.exhaustMessage, TALKTYPE_MONSTER_SAY) + end + return true + end + end + -- The Rookie Guard Quest - Mission 09: Rock 'n Troll -- Path: data\scripts\actions\quests\the_rookie_guard\mission09_rock_troll.lua -- Damage tunnel pillars @@ -957,12 +990,18 @@ function onUseScythe(player, item, fromPosition, target, toPosition, isHotkey) target:decay() Game.createItem(30975, 1, toPosition) return true - -- The secret library + -- The Secret Library Quest elseif toPosition == Position(32177, 31925, 7) then - player:teleportTo({ x = 32515, y = 32535, z = 12 }) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LibraryPermission) == 7 then + player:teleportTo({ x = 32515, y = 32535, z = 12 }) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + else + Position(32177, 31925, 7):sendMagicEffect(CONST_ME_POFF) + end else return false end + return onDestroyItem(player, item, fromPosition, target, toPosition, isHotkey) end @@ -971,6 +1010,23 @@ function onUseKitchenKnife(player, item, fromPosition, target, toPosition, isHot return false end + -- The Secret Library Quest + local tPos = toPosition + for _, j in pairs(secret_library.crystals) do + if tPos == j.position then + if player:getStorageValue(j.storage) < os.time() then + local r = math.random(1, 3) + local item_id = secret_library.items[r] + player:addItem(item_id, 1) + player:say("You have found a " .. ItemType(item_id):getName() .. ".", TALKTYPE_MONSTER_SAY) + player:setStorageValue(j.storage, os.time() + 2 * 60) + else + player:say(secret_library.exhaustMessage, TALKTYPE_MONSTER_SAY) + end + return true + end + end + local targetId = target:getId() --The Ice Islands Quest - Cure the Dogs diff --git a/data-otservbr-global/scripts/movements/teleport/falcon_castle.lua b/data-otservbr-global/scripts/movements/teleport/falcon_castle.lua deleted file mode 100644 index a7473748602..00000000000 --- a/data-otservbr-global/scripts/movements/teleport/falcon_castle.lua +++ /dev/null @@ -1,71 +0,0 @@ -local teleports = { - { position = { x = 33306, y = 31349, z = 8 }, destination = Position(33349, 31346, 8) }, - { position = { x = 33310, y = 31325, z = 8 }, access = Storage.TheSecretLibrary.OberonAccess, destination = Position(33329, 31332, 9) }, - { position = { x = 33329, y = 31333, z = 9 }, destination = Position(33308, 31325, 8) }, - { - positions = { - { x = 33296, y = 31287, z = 9 }, - { x = 33297, y = 31287, z = 9 }, - { x = 33298, y = 31287, z = 9 }, - { x = 33296, y = 31288, z = 9 }, - { x = 33298, y = 31288, z = 9 }, - { x = 33298, y = 31289, z = 9 }, - { x = 33297, y = 31289, z = 9 }, - }, - destination = Position(33363, 31342, 9), - }, -} - -local falconCastle = MoveEvent() - -function falconCastle.onStepIn(creature, item, position, fromPosition) - local player = creature:getPlayer() - if not player then - return false - end - for c = 1, #teleports do - if teleports[c].position then - if player:getPosition() == Position(teleports[c].position) then - if teleports[c].access then - if player:getStorageValue(teleports[c].access) == 1 then - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - player:teleportTo(teleports[c].destination) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - else - player:teleportTo(fromPosition) - end - else - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - player:teleportTo(teleports[c].destination) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end - end - elseif teleports[c].positions then - for d = 1, #teleports[c].positions do - if player:getPosition() == Position(teleports[c].positions[d]) then - if player:getStorageValue(Storage.TheSecretLibrary.TheOrderOfTheFalcon.OberonTimer) > os.time() then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have faced this boss in the last 20 hours.") - player:teleportTo(fromPosition) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - return false - else - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - player:teleportTo(teleports[c].destination) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end - end - end - end - end -end - -for a = 1, #teleports do - if teleports[a].position then - falconCastle:position(teleports[a].position) - elseif teleports[a].positions then - for b = 1, #teleports[a].positions do - falconCastle:position(teleports[a].positions[b]) - end - end -end -falconCastle:register() diff --git a/data-otservbr-global/scripts/quests/cradle_of_monsters/the_monster_fight.lua b/data-otservbr-global/scripts/quests/cradle_of_monsters/the_monster_fight.lua index ac10eead616..d85bd3491e5 100644 --- a/data-otservbr-global/scripts/quests/cradle_of_monsters/the_monster_fight.lua +++ b/data-otservbr-global/scripts/quests/cradle_of_monsters/the_monster_fight.lua @@ -196,6 +196,7 @@ local function setShields(creature, count) end local monsterHealth = CreatureEvent("fight.the-monster.TheMonsterHealth") + function monsterHealth.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType) if not creature then return primaryDamage, primaryType, secondaryDamage, secondaryType diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_analyser.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_analyser.lua index 17b7ffbc976..ce01d36c244 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_analyser.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_analyser.lua @@ -14,9 +14,9 @@ function cultsOfTibiaAnalyser.onUse(player, item, fromPosition, target, toPositi return false end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 4 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 4 then if target:getPosition() == sqm or target:getPosition() == Position(sqm.x, sqm.y + 1, sqm.z) or target:getPosition() == Position(sqm.x, sqm.y + 2, sqm.z) then - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 5) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 5) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Well done! The water is analyzed.") end end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_bosses_levers.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_bosses_levers.lua index 61fb460fd72..cf30097533c 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_bosses_levers.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_bosses_levers.lua @@ -34,7 +34,7 @@ end local function spawnDarkSoul(area, t_time) if t_time == 0 then - local esperandoPlayer = false + local waitingForPlayer = false local p1 = Position(33023, 31904, 14) local p2 = Position(33037, 31915, 14) local sA1 = Position(33028, 31908, 14) @@ -51,45 +51,43 @@ local function spawnDarkSoul(area, t_time) if not isPlayerInArea(a1, a2) then return true end - esperandoPlayer = true + waitingForPlayer = true else - local monster = {} + local monsters = {} for _x = sA1.x, sA2.x, 1 do for _y = sA1.y, sA2.y, 1 do local tileMonster = Tile(Position(_x, _y, sA1.z)):getTopCreature() if tileMonster and tileMonster:isMonster() and tileMonster:getName() == "Dark Soul" then - monster[#monster + 1] = tileMonster + monsters[#monsters + 1] = tileMonster end end end - if #monster >= 4 then - for _, pid in pairs(monster) do + if #monsters >= 4 then + for _, pid in pairs(monsters) do pid:remove() end end - -- spawn local newPos = Position(math.random(sA1.x, sA2.x), math.random(sA1.y, sA2.y), math.random(sA1.z, sA2.z)) Game.createMonster("Dark Soul", newPos) end - addEvent(spawnDarkSoul, 1000, area, (esperandoPlayer and 1 or 30)) + addEvent(spawnDarkSoul, 1000, area, (waitingForPlayer and 1 or 30)) else addEvent(spawnDarkSoul, 1000, area, t_time - 1) end end local function transformMonster(itid, action, monster, frompos, topos, _temp) - -- minotaur idol if action == 1 then - local tempo = _temp + local delay = _temp for _x = frompos.x, topos.x, 1 do local tile = Tile(Position(_x, frompos.y, frompos.z)) if _x % 2 == 0 then - tempo = tempo + 1 + delay = delay + 1 if tile then if tile:getItemCountById(itid) < 1 then Game.createItem(itid, 1, Position(_x, frompos.y, frompos.z)) end - addEvent(transformMonster, tempo * 15000, itid, 2, monster, Position(_x, frompos.y, frompos.z), {}, _temp + 1) + addEvent(transformMonster, delay * 15000, itid, 2, monster, Position(_x, frompos.y, frompos.z), {}, _temp + 1) end end end @@ -110,31 +108,31 @@ local function transformMonster(itid, action, monster, frompos, topos, _temp) end end -local function ativarGeyser(player) - local frompos = Position(33119, 31913, 15) -- Checagem - local topos = Position(33142, 31936, 15) -- Checagem +local function activateGeyser(player) + local frompos = Position(33119, 31913, 15) + local topos = Position(33142, 31936, 15) if isPlayerInArea(frompos, topos) then addEvent(function() local rand = math.random(1, 12) local geyserPos = Position(geyser[rand]) - local checar1 = Tile(Position(geyserPos)):getItemById(25509) - if checar1 then + local check1 = Tile(Position(geyserPos)):getItemById(25509) + if check1 then addEvent(function() local player1 = Game.getPlayers()[1] Game.createItem(25510, 1, geyserPos) player1:say("SPLASH!", TALKTYPE_MONSTER_SAY, false, false, geyserPos) addEvent(function() - local checar2 = Tile(Position(geyserPos)):getItemById(25510) - if checar2 then - checar2:remove() + local check2 = Tile(Position(geyserPos)):getItemById(25510) + if check2 then + check2:remove() end end, 9 * 1000) end, 5 * 1000) - elseif checar2 then + elseif check2 then return false end addEvent(function() - ativarGeyser() + activateGeyser() end, 1 * 1000) end, 8 * 1000) end @@ -142,6 +140,7 @@ local function ativarGeyser(player) end local cultsOfTibiaLevers = Action() + function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition) local players = {} local ittable = {} @@ -149,19 +148,26 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition local convertTable = {} item:transform(transformid[item:getId()]) - if item:getActionId() == 5501 and item:getId() == 8912 then -- Leiden + if item:getActionId() == 5501 and item:getId() == 8912 then if player:getPosition() == Position(33138, 31953, 15) then local teleport = 0 - for i = 31953, 31957, 1 do + local playersInArea = {} + local frompos = Position(33151, 31942, 15) + local topos = Position(33176, 31966, 15) + + for i = 31953, 31957 do local newpos = Position(33138, i, 15) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33151, 31942, 15) -- Checagem - local topos = Position(33176, 31966, 15) -- Checagem + if teleport ~= 5 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("The room is full.") @@ -179,36 +185,41 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for i = 31953, 31957, 1 do - local newpos = Position(33138, i, 15) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("Ravenous Hunger", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33161, 31959, 15), true) - nplayer:sendBosstiaryCooldownTimer() - convertTable[#convertTable + 1] = nplayer:getId() - nplayer:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("Ravenous Hunger", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33161, 31959, 15), true) + nplayer:sendBosstiaryCooldownTimer() + convertTable[#convertTable + 1] = nplayer:getId() + nplayer:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + Game.createMonster("Wine Cask", Position(33162, 31945, 15)) local leiden = Game.createMonster("Leiden", Position(33162, 31950, 15)) leiden:setHealth(leiden:getHealth() / 2) kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33121, 31951, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) end end - if item:getActionId() == 5502 and item:getId() == 8912 then -- The False God + + if item:getActionId() == 5502 and item:getId() == 8912 then if player:getPosition() == Position(33162, 31893, 15) then local teleport = 0 - for i = 31893, 31897, 1 do + local playersInArea = {} + local frompos = Position(33152, 31908, 15) + local topos = Position(33175, 31923, 15) + + for i = 31893, 31897 do local newpos = Position(33162, i, 15) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33152, 31908, 15) -- Checagem - local topos = Position(33175, 31923, 15) -- Checagem + if teleport ~= 5 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("The room is full.") @@ -226,38 +237,41 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for i = 31893, 31897, 1 do - local newpos = Position(33162, i, 15) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("The False God", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33169, 31915, 15), true) - convertTable[#convertTable + 1] = nplayer:getId() - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("The False God", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33169, 31915, 15), true) + convertTable[#convertTable + 1] = nplayer:getId() + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + transformMonster(25300, 1, "minotaur idol", Position(33157, 31910, 15), Position(33168, 31910, 15), 0) transformMonster(25300, 1, "minotaur idol", Position(33158, 31921, 15), Position(33168, 31921, 15), 6) addEvent(transformMonster, 13 * 15000, 3, 3, "Sphere Of Wrath", {}, {}, 0) Game.createMonster("The False God", Position(33159, 31914, 15)) - -- funçao kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33181, 31894, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) end end - if item:getActionId() == 5500 then -- Essence of Malice + if item:getActionId() == 5500 then if player:getPosition() == Position(33095, 31943, 15) and item:getId() == 8912 then local teleport = 0 - for i = 31943, 31947, 1 do + local playersInArea = {} + local frompos = Position(33084, 31907, 15) + local topos = Position(33114, 31933, 15) + + for i = 31943, 31947 do local newpos = Position(33095, i, 15) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33084, 31907, 15) -- Checagem - local topos = Position(33114, 31933, 15) -- Checagem + if teleport ~= 1 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("It looks like there is someone inside.") @@ -275,16 +289,13 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for i = 31943, 31947, 1 do - local newpos = Position(33095, i, 15) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("Essence of Malice", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33098, 31921, 15), true) - convertTable[#convertTable + 1] = nplayer:getId() - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("Essence of Malice", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33098, 31921, 15), true) + convertTable[#convertTable + 1] = nplayer:getId() + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33091, 31963, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) Game.createMonster("Pillar of Summoning", Position(33093, 31919, 15)) Game.createMonster("Pillar of Death", Position(33098, 31915, 15)) @@ -299,19 +310,26 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - if item:getActionId() == 5503 then -- The Souldespoiler + if item:getActionId() == 5503 then if player:getPosition() == Position(33127, 31892, 15) and item:getId() == 8912 then local teleport = 0 - for i = 31892, 31896, 1 do + local playersInArea = {} + local frompos = Position(33119, 31913, 15) + local topos = Position(33142, 31936, 15) + + for i = 31892, 31896 do local newpos = Position(33127, i, 15) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33119, 31913, 15) -- Checagem - local topos = Position(33142, 31936, 15) -- Checagem + if teleport ~= 5 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("It looks like there is someone inside.") @@ -329,35 +347,39 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for i = 31892, 31896, 1 do - local newpos = Position(33127, i, 15) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("The Souldespoiler", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33130, 31919, 15), true) - convertTable[#convertTable + 1] = nplayer:getId() - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("The Souldespoiler", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33130, 31919, 15), true) + convertTable[#convertTable + 1] = nplayer:getId() + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33109, 31887, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) Game.createMonster("The Sinister Hermit Dirty", Position(33131, 31925, 15)) - ativarGeyser() + activateGeyser() end end - if item:getActionId() == 5504 then -- Boss do orc + if item:getActionId() == 5504 then if player:getPosition() == Position(33164, 31859, 15) and item:getId() == 8912 then local teleport = 0 - for y = 31859, 31863, 1 do + local playersInArea = {} + local frompos = Position(33123, 31846, 15) + local topos = Position(33149, 31871, 15) + + for y = 31859, 31863 do local newpos = Position(33164, y, 15) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33123, 31846, 15) -- Checagem - local topos = Position(33149, 31871, 15) -- Checagem + if teleport ~= 5 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("It looks like there is someone inside.") @@ -375,17 +397,14 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for y = 31859, 31863, 1 do - local newpos = Position(33164, y, 15) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("The Armored Voidborn", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33137, 31867, 15), true) - convertTable[#convertTable + 1] = nplayer:getId() - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("The Armored Voidborn", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33137, 31867, 15), true) + convertTable[#convertTable + 1] = nplayer:getId() + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end - local function criarRaio1(fromPos, toPos, id, dir) + + local function createBeam1(fromPos, toPos, id, dir) if dir == 1 then for _x = fromPos.x, toPos.x, 1 do local tile = Tile(Position(_x, fromPos.y, fromPos.z)) @@ -402,26 +421,26 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end end - local itensToMonster = { --8633 + + local itemsToMonster = { Position(33133, 31856, 15), Position(33140, 31856, 15), Position(33140, 31863, 15), Position(33133, 31863, 15), } - -- criando os itens - for _, position in pairs(itensToMonster) do + + for _, position in pairs(itemsToMonster) do local tile = Tile(position) if tile and tile:getItemCountById(7805) < 1 then Game.createItem(7805, 1, position) end end - -- criando os raios - criarRaio1(Position(33134, 31856, 15), Position(33139, 31856, 15), 6116, 1) - criarRaio1(Position(33134, 31863, 15), Position(33139, 31863, 15), 6116, 1) - criarRaio1(Position(33140, 31857, 15), Position(33140, 31862, 15), 6117, 2) - criarRaio1(Position(33133, 31857, 15), Position(33133, 31862, 15), 6117, 2) - -- criando os securys + createBeam1(Position(33134, 31856, 15), Position(33139, 31856, 15), 6116, 1) + createBeam1(Position(33134, 31863, 15), Position(33139, 31863, 15), 6116, 1) + createBeam1(Position(33140, 31857, 15), Position(33140, 31862, 15), 6117, 2) + createBeam1(Position(33133, 31857, 15), Position(33133, 31862, 15), 6117, 2) + Game.createMonster("Security Golem", Position(33131, 31855, 15)) Game.createMonster("Security Golem", Position(33142, 31855, 15)) Game.createMonster("Security Golem", Position(33141, 31863, 15)) @@ -432,19 +451,28 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33179, 31840, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) end end - if item:getActionId() == 5505 then -- Boss da areia + + if item:getActionId() == 5505 then if player:getPosition() == Position(33507, 32228, 10) and item:getId() == 8912 then local teleport = 0 - for _y = 32228, 32232, 1 do + local teleport = 0 + local playersInArea = {} + local frompos = Position(33087, 31848, 15) + local topos = Position(33109, 31871, 15) + + for _y = 32228, 32232 do local newpos = Position(33507, _y, 10) local nplayer = Tile(newpos):getTopCreature() if nplayer and nplayer:isPlayer() then teleport = teleport + 1 + table.insert(playersInArea, nplayer) end end - local frompos = Position(33087, 31848, 15) -- Checagem - local topos = Position(33109, 31871, 15) -- Checagem + if teleport ~= 5 then + player:sendCancelMessage("You need exactly 5 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("It looks like there is someone inside.") @@ -472,15 +500,11 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - for _y = 32228, 32232, 1 do - local newpos = Position(33507, _y, 10) - local nplayer = Tile(newpos):getTopCreature() - if nplayer and nplayer:isPlayer() then - nplayer:setBossCooldown("The Sandking", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33099, 31864, 15), true) - convertTable[#convertTable + 1] = nplayer:getId() - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("The Sandking", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33099, 31864, 15), true) + convertTable[#convertTable + 1] = nplayer:getId() + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end Game.createMonster("the sandking fake", Position(33099, 31858, 15)):registerEvent("SandkingThink") @@ -489,39 +513,67 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition end end - -- final boss if item:getActionId() == 5506 then if player:getPosition() == Position(33074, 31884, 15) and item:getId() == 8912 then - local convertTable = {} - convertTable[#convertTable + 1] = player:getId() + local teleport = 0 + local playersInArea = {} + local frompos = Position(33023, 31904, 14) + local topos = Position(33052, 31932, 15) + + if player:getPosition() == Position(33074, 31884, 15) then + teleport = teleport + 1 + table.insert(playersInArea, player) + else + return true + end + + local pt1 = Position(33073, 31885, 15) + local pt2 = Position(33075, 31887, 15) + for _x = pt1.x, pt2.x do + for _y = pt1.y, pt2.y do + local nplayer = Tile(Position(_x, _y, 15)):getTopCreature() + if nplayer and nplayer:isPlayer() then + teleport = teleport + 1 + table.insert(playersInArea, nplayer) + end + end + end - local frompos = Position(33023, 31904, 14) -- Checagem - local topos = Position(33052, 31932, 15) -- Checagem + if teleport ~= 10 then + player:sendCancelMessage("You need exactly 10 players to start this challenge.") + return true + end if isPlayerInArea(frompos, topos) then player:sendCancelMessage("It looks like there is someone inside.") return true end - local pt1 = Position(33073, 31885, 15) - local pt2 = Position(33075, 31887, 15) - for _x = pt1.x, pt2.x, 1 do - for _y = pt1.y, pt2.y, 1 do - for _z = pt1.z, pt2.z, 1 do - local nplayer = Tile(Position(_x, _y, _z)):getTopCreature() - if nplayer and nplayer:isPlayer() then - convertTable[#convertTable + 1] = nplayer:getId() + for _x = frompos.x, topos.x do + for _y = frompos.y, topos.y do + for _z = frompos.z, topos.z do + local tile = Tile(Position(_x, _y, _z)) + if tile and tile:getTopCreature() and tile:getTopCreature():isMonster() then + tile:getTopCreature():remove() + end + if tile then + local tileItems = tile:getItems() + if type(tileItems) == "table" and #tileItems > 0 then + for _, it in pairs(tileItems) do + if ItemType(it:getId()):isCorpse() then + it:remove() + end + end + end end end end end - for _, pid in pairs(convertTable) do - local nplayer = Player(pid) - if nplayer then - nplayer:setBossCooldown("The Source Of Corruption", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) - nplayer:teleportTo(Position(33039, 31925, 15), true) - nplayer:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end + + for _, nplayer in ipairs(playersInArea) do + nplayer:setBossCooldown("The Source Of Corruption", os.time() + configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN)) + nplayer:teleportTo(Position(33039, 31925, 15), true) + nplayer:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end Game.createMonster("The Remorseless Corruptor", Position(33039, 31922, 15)) @@ -531,9 +583,11 @@ function cultsOfTibiaLevers.onUse(player, item, fromPosition, itemEx, toPosition spawnDarkSoul(1, 30) spawnDarkSoul(2, 30) spawnStolenSoul(30) - kickerPlayerRoomAfterMin(convertTable, frompos, topos, Position(33072, 31867, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) + + kickerPlayerRoomAfterMin(playersInArea, frompos, topos, Position(33072, 31867, 15), "You were kicked for exceeding the time limit within the boss room.", "", 60, true, ittable, blockmonsters) end end + return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_counter_agent.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_counter_agent.lua index b59b1508430..24b414399ee 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_counter_agent.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_counter_agent.lua @@ -27,10 +27,10 @@ function cultsOfTibiaCounter.onUse(player, item, fromPosition, target, toPositio return false end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 6 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 6 then if target:getPosition() == sqm or target:getPosition() == Position(sqm.x, sqm.y + 1, sqm.z) or target:getPosition() == Position(sqm.x, sqm.y + 2, sqm.z) then player:teleportTo(destino) - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 7) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 7) for i, position in pairs(config) do position:sendMagicEffect(CONST_ME_POFF) end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_crate.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_crate.lua index 0cc39a78e51..33ef2a91c0f 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_crate.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_crate.lua @@ -3,11 +3,11 @@ function cultsOfTibiaCrate.onUse(player, item, fromPosition, target, toPosition, local posCrate = Position(33300, 32277, 12) -- Document if item:getPosition() == posCrate then - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 7 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 7 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Perfect! You took a wonderful loupe from this crate.") player:addItem(25306, 1) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 8) - elseif player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) > 7 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 8) + elseif player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) > 7 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already took the magnifier.") else player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This crate belongs to Angelo. You should talk to him before taking something out.") diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_cult_symbol.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_cult_symbol.lua index 80a23f7eb63..6663a616b27 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_cult_symbol.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_cult_symbol.lua @@ -16,12 +16,11 @@ local config = { local cultsOfTibiaCult = Action() function cultsOfTibiaCult.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local stg = math.max(player:getStorageValue(Storage.CultsOfTibia.Barkless.Objects), 0) + local stg = math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects), 0) if stg >= 10 then - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Mission) >= 4 then - -- continue + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission) >= 4 then else - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 4) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, 4) end return false end @@ -32,19 +31,19 @@ function cultsOfTibiaCult.onUse(player, item, fromPosition, target, toPosition, break end end - local stgTemp = math.max(player:getStorageValue(Storage.CultsOfTibia.Barkless.Temp), 0) + local stgTemp = math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Temp), 0) local manchaMeta = NewBit(stgTemp) local base = bit.lshift(1, mancha.base) if manchaMeta:hasFlag(base) then return false end manchaMeta:updateFlag(base) - player:setStorageValue(Storage.CultsOfTibia.Barkless.Temp, manchaMeta:getNumber()) - player:setStorageValue(Storage.CultsOfTibia.Barkless.Objects, stg + 1) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Objects) >= 10 then - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 4) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Temp, manchaMeta:getNumber()) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects, stg + 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects) >= 10 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, 4) end - local msg = (player:getStorageValue(Storage.CultsOfTibia.Barkless.Objects) < 10 and "Your body reacts to this strange green substance as you reach out to touch it. You feel an urge for more of this energy." or "You gathered an impressive amount of power from simply touching the strange green symbols of the Barkless. But how...?") + local msg = (player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Objects) < 10 and "Your body reacts to this strange green substance as you reach out to touch it. You feel an urge for more of this energy." or "You gathered an impressive amount of power from simply touching the strange green symbols of the Barkless. But how...?") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, msg) return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_document.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_document.lua index 50c81e864b6..93b96264d53 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_document.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_document.lua @@ -1,17 +1,18 @@ local cultsOfTibiaDocument = Action() + function cultsOfTibiaDocument.onUse(player, item, fromPosition, target, toPosition, isHotkey) local posDocument = Position(33279, 32169, 8) - -- Document if item:getPosition() == posDocument then - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 2 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Dear curator, this recently opened museum is a really nice place to be.") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "But wait! What about the empty space in front of you? What a pity!") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "It seems that somebody has removed one of the beautiful pictures. But come on! You have the money and we need it.") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "So for a small expense allowance you'll get it back. Just talk to Iwar in Kazordoon for further information. ") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Ask him: Has the cat got your tongue?") - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 3) end end + return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_last_object.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_last_object.lua index 565da77e68c..be82c316271 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_last_object.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_last_object.lua @@ -14,16 +14,17 @@ local config = { } local cultsOfTibiaLastObject = Action() + function cultsOfTibiaLastObject.onUse(player, item) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Mission) == 4 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission) == 4 then for i, position in pairs(config) do position:sendMagicEffect(CONST_ME_YELLOWENERGY) end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The strange symbol in the wall in the back glows violently.") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The cult object just lies there quietly. The dangerous area around it has been all but dissolved.") player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "As you reach out to touch the cult object, a surge of energy burst from the skull. You banished its power.") - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 5) - player:setStorageValue(Storage.CultsOfTibia.Barkless.BossAccessDoor, 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, 5) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.BossAccessDoor, 1) end return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_lever_mota.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_lever_mota.lua index 03aaf3b2004..51035795573 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_lever_mota.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_lever_mota.lua @@ -4,55 +4,62 @@ local transformid = { } local cultsOfTibiaLeverMota = Action() + function cultsOfTibiaLeverMota.onUse(player, item, fromPosition, itemEx, toPosition) - local posPedra = Position() - local posPedra2 = Position() - local posPedra3 = Position() - local pedraid = 15487 - if player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) ~= 12 then + local stonePos1 = Position() + local stonePos2 = Position() + local stonePos3 = Position() + local stoneId = 15487 + + local missionStatus = player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) + if missionStatus ~= 12 and missionStatus ~= 13 then player:getPosition():sendMagicEffect(CONST_ME_POFF) return false end - for i = 33300, 33305, 1 do + + for i = 33300, 33305 do local newpos = Position(i, 32144, 10) - if Tile(newpos):getItemCountById(pedraid) == 1 then - posPedra = newpos + if Tile(newpos):getItemCountById(stoneId) == 1 then + stonePos1 = newpos end newpos = Position(i, 32146, 10) - if Tile(newpos):getItemCountById(pedraid) == 1 then - posPedra2 = newpos + if Tile(newpos):getItemCountById(stoneId) == 1 then + stonePos2 = newpos end newpos = Position(i, 32148, 10) - if Tile(newpos):getItemCountById(pedraid) == 1 then - posPedra3 = newpos + if Tile(newpos):getItemCountById(stoneId) == 1 then + stonePos3 = newpos end end - local pedra1 = math.random(0, 5) - local pedra2 = math.random(0, 5) - local pedra3 = math.random(0, 5) - -- pedra 1 - local itpedra1 = Tile(posPedra):getItemById(pedraid) - local newpos = { x = 33300 + pedra1, y = itpedra1:getPosition().y, z = itpedra1:getPosition().z } - itpedra1:moveTo(newpos) + + local stone1 = math.random(0, 5) + local stone2 = math.random(0, 5) + local stone3 = math.random(0, 5) + + local itstone1 = Tile(stonePos1):getItemById(stoneId) + local newpos = { x = 33300 + stone1, y = itstone1:getPosition().y, z = itstone1:getPosition().z } + itstone1:moveTo(newpos) Position(newpos):sendMagicEffect(CONST_ME_POFF) - -- pedra 2 - local itpedra2 = Tile(posPedra2):getItemById(pedraid) - local newpos = { x = 33300 + pedra2, y = itpedra2:getPosition().y, z = itpedra2:getPosition().z } - itpedra2:moveTo(newpos) + local itstone2 = Tile(stonePos2):getItemById(stoneId) + local newpos = { x = 33300 + stone2, y = itstone2:getPosition().y, z = itstone2:getPosition().z } + itstone2:moveTo(newpos) Position(newpos):sendMagicEffect(CONST_ME_POFF) - -- pedra 3 - local itpedra3 = Tile(posPedra3):getItemById(pedraid) - local newpos = { x = 33300 + pedra3, y = itpedra3:getPosition().y, z = itpedra3:getPosition().z } - itpedra3:moveTo(newpos) + local itstone3 = Tile(stonePos3):getItemById(stoneId) + local newpos = { x = 33300 + stone3, y = itstone3:getPosition().y, z = itstone3:getPosition().z } + itstone3:moveTo(newpos) Position(newpos):sendMagicEffect(CONST_ME_POFF) - player:setStorageValue(Storage.CultsOfTibia.MotA.Stone1, Stone1) - player:setStorageValue(Storage.CultsOfTibia.MotA.Stone2, Stone2) - player:setStorageValue(Storage.CultsOfTibia.MotA.Stone3, Stone3) - player:setStorageValue(Storage.CultsOfTibia.MotA.AccessDoorGareth, -1) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) + 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone1, stone1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone2, stone2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Stone3, stone3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorGareth, -1) + + if missionStatus == 12 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 13) + end + item:transform(transformid[item:getId()]) return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_magnifier.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_magnifier.lua index 449e79dc115..e50f94226b0 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_magnifier.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_magnifier.lua @@ -18,9 +18,9 @@ function cultsOfTibiaMagnifier.onUse(player, item, fromPosition, target, toPosit if table.contains({ 2622, 2601, 2596, 2612, 2618 }, target:getId()) then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Nothing special. This picture looks genuine.") target:getPosition():sendMagicEffect(CONST_ME_POFF) - elseif target:getPosition() == sqm and target:getId() == 2613 and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) == 8 then + elseif target:getPosition() == sqm and target:getId() == 2613 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) == 8 then target:getPosition():sendMagicEffect(CONST_ME_POFF) - player:setStorageValue(Storage.CultsOfTibia.MotA.Mission, 9) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission, 9) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This is it. It looks like it was painted by a child!") end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_misguided.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_misguided.lua index 3c555338d21..42b81b970db 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_misguided.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_misguided.lua @@ -39,22 +39,26 @@ local function changeMap(mapName) end local cultsOfTibiaMisguided = Action() + function cultsOfTibiaMisguided.onUse(player, item, position, target, targetPosition) - local monster = Monster(target) - if not monster then + local creature = Creature(target) + if not creature then return false end + local map = (type(Game.getStorageValue("cultsMap")) == "string" and Game.getStorageValue("cultsMap") or "illusion") - if monster:getName():lower() == "misguided bully" or monster:getName():lower() == "misguided thief" then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Monsters, 0) + if creature:getName():lower() == "misguided bully" or creature:getName():lower() == "misguided thief" then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters, 0) item:remove(1) - local pos = monster:getPosition() + local pos = creature:getPosition() Game.createItem(25298, 1, pos) - monster:remove() - local newMonster = Game.createMonster("Misguided Shadow", pos) - if newMonster then - newMonster:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + creature:remove() + + local newCreature = Game.createMonster("Misguided Shadow", pos) + if newCreature then + newCreature:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You paralyse the bully and the amulet reveals the true face of the creature behind the possession of this misguided creature.") local it = player:addItem(25296, 1) if map == "illusion" then @@ -62,6 +66,7 @@ function cultsOfTibiaMisguided.onUse(player, item, position, target, targetPosit end it:decay() end + return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_torch.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_torch.lua index c60e5d024b8..7b1d8c4826e 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/actions_torch.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/actions_torch.lua @@ -3,9 +3,11 @@ local config = { } local cultsOfTibiaTouch = Action() + function cultsOfTibiaTouch.onUse(player, item, fromPosition, target, toPosition, isHotkey) local wallItem - if Game.getStorageValue(12345) >= os.time() then + + if Game.getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.WallDecaying) >= os.time() then player:getPosition():sendMagicEffect(CONST_ME_POFF) else for i = 1, #config do @@ -14,11 +16,12 @@ function cultsOfTibiaTouch.onUse(player, item, fromPosition, target, toPosition, Position(32396, 31806, 8):sendMagicEffect(CONST_ME_POFF) wallItem:remove() player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You hear a loud grinding sound not very far from you. something very heavy seems to have moved.") - Game.setStorageValue(12345, os.time() + 306) + Game.setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.WallDecaying, os.time() + 306) addEvent(Game.createItem, 300000, 1295, 1, Position(32396, 31806, 8)) end end end + return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_bosses_mission_cults.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_bosses_mission_cults.lua index bd4da1601f1..5ce125af212 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_bosses_mission_cults.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_bosses_mission_cults.lua @@ -1,12 +1,12 @@ local bosses = { - ["ravenous hunger"] = { storage = Storage.CultsOfTibia.Barkless.Mission, value = 6 }, - ["the souldespoiler"] = { storage = Storage.CultsOfTibia.Misguided.Mission, value = 4 }, - ["essence of malice"] = { storage = Storage.CultsOfTibia.Humans.Mission, value = 2 }, - ["the unarmored voidborn"] = { storage = Storage.CultsOfTibia.Orcs.Mission, value = 2 }, - ["the false god"] = { storage = Storage.CultsOfTibia.Minotaurs.Mission, value = 4 }, - ["the sandking"] = { storage = Storage.CultsOfTibia.Life.Mission, value = 8, global = "sandking", g_value = 5 }, + ["ravenous hunger"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, value = 6 }, + ["the souldespoiler"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, value = 4 }, + ["essence of malice"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Mission, value = 2 }, + ["the unarmored voidborn"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Orcs.Mission, value = 2 }, + ["the false god"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Minotaurs.Mission, value = 4 }, + ["the sandking"] = { storage = Storage.Quest.U11_40.CultsOfTibia.Life.Mission, value = 8, global = "sandking", g_value = 5 }, ["the corruptor of souls"] = { createNew = "The Source Of Corruption", pos = Position(33039, 31922, 15), removeMonster = "zarcorix of yalahar", area1 = Position(33073, 31885, 15), area2 = Position(33075, 31887, 15) }, - ["the source of corruption"] = { storage = Storage.CultsOfTibia.FinalBoss.Mission, value = 2 }, + ["the source of corruption"] = { storage = Storage.Quest.U11_40.CultsOfTibia.FinalBoss.Mission, value = 2 }, } local bossesCults = CreatureEvent("CultsOfTibiaBossDeath") diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_glowing_rubbish_amulet.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_glowing_rubbish_amulet.lua index 55a16295bb3..a5fbfcc60f4 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_glowing_rubbish_amulet.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_glowing_rubbish_amulet.lua @@ -1,27 +1,31 @@ local glowingRubbishAmulet = CreatureEvent("GlowingRubbishAmuletDeath") + function glowingRubbishAmulet.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) onDeathForParty(creature, mostDamageKiller, function(creature, player) local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) - if not amulet or amulet:getId() ~= 25296 then - return true - end - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) ~= 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) ~= 3 then return true end - local mStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters), 0) - local eStg = math.max(player:getStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms), 0) - if monster:getName():lower() == "misguided shadow" then + local mStg = math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters), 0) + local eStg = math.max(player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Exorcisms), 0) + + if creature:getName():lower():trim() == "misguided shadow" then if eStg < 5 then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms, eStg + 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Exorcisms, eStg + 1) end return true end - if monster:getName():lower() == "misguided bully" or monster:getName():lower() == "misguided thief" then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Monsters, mStg + 1) - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters) >= 10 then + if not amulet or amulet:getId() ~= 25296 then + return true + end + + if creature:getName():lower():trim() == "misguided bully" or creature:getName():lower():trim() == "misguided thief" then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters, mStg + 1) + + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters) >= 10 then amulet:remove() local it = player:addItem(25297, 1) if it then diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_minotaur_task_count.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_minotaur_task_count.lua index 68f3a0f93a1..267bc2e5d06 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_minotaur_task_count.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_minotaur_task_count.lua @@ -1,9 +1,9 @@ local minotaurTask = CreatureEvent("MinotaurCultTaskDeath") function minotaurTask.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) onDeathForParty(creature, mostDamageKiller, function(creature, player) - local storage = player:getStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask) + local storage = player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask) if storage >= 0 and storage < 50 then - player:setStorageValue(Storage.CultsOfTibia.Minotaurs.JamesfrancisTask, storage + 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Minotaurs.JamesfrancisTask, storage + 1) end end) return true diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_splash.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_splash.lua index 17af493a144..bf8b0ac2d59 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_splash.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/creaturescripts_splash.lua @@ -1,4 +1,5 @@ local splash = CreatureEvent("Splash") + function splash.onThink(creature) local hp = (creature:getHealth() / creature:getMaxHealth()) * 100 if hp < 85.0 then diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_begin_task.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_begin_task.lua index f1bf05f4b08..fb8a88cdb0b 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_begin_task.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_begin_task.lua @@ -1,4 +1,4 @@ -function fallFloor(pid, id) +local function fallFloor(pid, id) local player = Player(pid) if not player then return true @@ -10,10 +10,11 @@ function fallFloor(pid, id) end local chance = math.random(0, 100) - if chance <= 1 then + if chance <= 2 then amulet:moveTo(player:getPosition()) end addEvent(fallFloor, 10000, player:getId(), id) + return true end @@ -24,19 +25,15 @@ function beginTask.onEquip(player, item, slot, isCheck) return true end - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) >= 2 and player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) <= 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) >= 2 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) <= 3 then local equippedBefore = item:getCustomAttribute("task") or 0 - if equippedBefore ~= player:getGuid() and player:getStorageValue(Storage.CultsOfTibia.Misguided.Monsters) < 10 then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Monsters, 0) + if equippedBefore ~= player:getGuid() and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters) < 10 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Monsters, 0) item:setCustomAttribute("task", player:getGuid()) end - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Mission) == 2 then - player:setStorageValue(Storage.CultsOfTibia.Misguided.Mission, 3) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "The amulet burns your skin. \z - It hungers for energy right now, gather a large amount of energy as fast as possible to charge it. " - ) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission) == 2 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Mission, 3) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The amulet burns your skin. It hungers for energy right now, gather a large amount of energy as fast as possible to charge it.") end end addEvent(fallFloor, 10000, player:getId(), item:getId()) diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_check_oasis.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_check_oasis.lua index 5a52cb16748..b4e769d0b29 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_check_oasis.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_check_oasis.lua @@ -6,9 +6,9 @@ function checkOasis.onStepIn(creature, item, position, fromPosition) return true end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) == 2 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a lovely oasis with green fauna and juicy fruit. You didn't expect that.") - player:setStorageValue(Storage.CultsOfTibia.Life.Mission, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission, 3) end return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_energy_fence.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_energy_fence.lua index 7f5314001b4..b8b035c8955 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_energy_fence.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_energy_fence.lua @@ -27,38 +27,26 @@ function energyFence.onStepIn(creature, item, position, fromPosition) end if position == firstCheck or position == Position(firstCheck.x + 1, firstCheck.y, firstCheck.z) or position == Position(firstCheck.x + 2, firstCheck.y, firstCheck.z) then - if player:getStorageValue(Storage.CultsOfTibia.Humans.Vaporized) == 10 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.Vaporized) == 10 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "With you being the vessel binding the power of whitered souls, you step through the magic barrier.") player:getPosition():sendMagicEffect(CONST_ME_ENERGYHIT) else player:teleportTo(fromPosition, true) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "The combined powers of decaying souls \z - roaming these halls may help breach this barrier, it needs but a vessel to bind them." - ) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The combined powers of decaying souls roaming these halls may help breach this barrier, it needs but a vessel to bind them.") end elseif position == secondCheck or position == Position(secondCheck.x + 1, secondCheck.y, secondCheck.z) then - if player:getStorageValue(Storage.CultsOfTibia.Humans.Decaying) == 10 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.Decaying) == 10 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "With you being the vessel binding the power of whitered souls, you step through the magic barrier.") player:getPosition():sendMagicEffect(CONST_ME_ENERGYHIT) else player:teleportTo(fromPosition, true) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "The combined powers of decaying souls \z - roaming these halls may help breach this barrier, it needs but a vessel to bind them." - ) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The combined powers of decaying souls roaming these halls may help breach this barrier, it needs but a vessel to bind them.") end elseif misguided then for i, position in pairs(misguided) do - if player:getStorageValue(Storage.CultsOfTibia.Misguided.Exorcisms) >= 5 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Misguided.Exorcisms) >= 5 then player:getPosition():sendMagicEffect(CONST_ME_ENERGYHIT) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "As you cross the threshold in to the inner \z - sanctuary of the cult of the Misguided, you feel an eerie presence all around you." - ) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "As you cross the threshold in to the inner sanctuary of the cult of the Misguided, you feel an eerie presence all around you.") break else player:teleportTo(fromPosition, true) diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice.lua index fe1340bb44f..13649dc1d6f 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice.lua @@ -1,5 +1,5 @@ -function sendConditionCults(playerid, info, fromPos, toPos, fromPos2, toPos2, time) - local player = Player(playerid) +local function sendConditionCults(playerId, info, fromPos, toPos, fromPos2, toPos2, time) + local player = Player(playerId) if not player then return false end @@ -20,16 +20,20 @@ function sendConditionCults(playerid, info, fromPos, toPos, fromPos2, toPos2, ti elseif time >= 120 then local storage = player:getStorageValue(info.storageBarkless) < 0 and 0 or player:getStorageValue(info.storageBarkless) if storage < 3 and storage ~= 1 and storage ~= 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[3]) - player:setStorageValue(info.storageBarkless, 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Sulphur) == 3 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar) == 3 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[3]) + player:setStorageValue(info.storageBarkless, 1) + else + return true + end end end player:getPosition():sendMagicEffect(info.effect) - addEvent(sendConditionCults, 2000, playerid, info, fromPos, toPos, fromPos2, toPos2, time) + addEvent(sendConditionCults, 2000, playerId, info, fromPos, toPos, fromPos2, toPos2, time) end -local function floorPassage(playerid, info, time) - local player = Player(playerid) +local function floorPassage(playerId, info, time) + local player = Player(playerId) if not player then return true end @@ -42,7 +46,7 @@ local function floorPassage(playerid, info, time) if storage == 3 then return true end - addEvent(floorPassage, 1000, playerid, info, time - 1) + addEvent(floorPassage, 1000, playerId, info, time - 1) end local ice = MoveEvent() @@ -58,16 +62,15 @@ function ice.onStepIn(creature, item, position, fromPosition) fromPos2 = Position(32696, 31429, 8), toPos2 = Position(32728, 31435, 8), effect = CONST_ME_GIANTICE, - firstSqm = Position(32698, 31405, 8), - storageBarkless = Storage.CultsOfTibia.Barkless.Ice, + firstTile = Position(32698, 31405, 8), + storageBarkless = Storage.Quest.U11_40.CultsOfTibia.Barkless.Ice, msgs = { - "As you enter the icy cavern, you feel an unnatural frostiness. \z - The ice cold air stings in your face. Survive and prove worthy.", -- on enter - "Your body temperature sinks. You can see your breath freezing in the cold.", -- 30/60 seconds + "As you enter the icy cavern, you feel an unnatural frostiness. The ice cold air stings in your face. Survive and prove worthy.", -- on enter + "Your body temperature sinks. You can see your breath freezing in the cold.", -- 30/60/90 seconds "The icy cold is grasping to you. You can barely move anymore.", -- 120 seconds - "You are now washed and ready to purify yourself in the chambers of purification.", -- step in the first tile - "You are now ready to prove your worth. Take heart and cross the threshold of ice.", -- step in the second tile - "You took so long. You are no longer purified.", -- there's no time to step + "You are now washed and ready to purify yourself in the chambers of purification.", -- step on the first tile + "You are now ready to prove your worth. Take heart and cross the threshold of ice.", -- step on the second tile + "You took so long. You are no longer purified.", -- didn't step in time }, } if fromPosition.y == 31441 then @@ -76,7 +79,7 @@ function ice.onStepIn(creature, item, position, fromPosition) return true end - if item:getPosition():compare(setting.firstSqm) then + if item:getPosition():compare(setting.firstTile) then if player:getStorageValue(setting.storageBarkless) ~= 1 then return true end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice_death.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice_death.lua index aff8d2462af..cd43068e0c3 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice_death.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_ice_death.lua @@ -1,11 +1,11 @@ function Player.sendFakeDeathWindow(self) - -- consider migrating to ProtocolGame::sendDeath local msg = NetworkMessage() + -- I found this in the function ProtocolGame::sendReLoginWindow msg:addByte(0x28) - msg:addByte(0x01) - msg:addByte(2) - msg:addByte(0x00) -- Use death redemption - msg:sendToPlayer(self, false) + msg:addByte(0x00) + msg:addByte(0x00) + msg:addByte(0x00) + msg:sendToPlayer(self) return true end @@ -44,9 +44,9 @@ function iceDeath.onStepIn(creature, item, position, fromPosition) if not player then return true end - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Ice) == 2 then - player:setStorageValue(Storage.CultsOfTibia.Barkless.Ice, 3) - player:setStorageValue(Storage.CultsOfTibia.Barkless.Death, 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Ice) == 2 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Ice, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Death, 1) for _, conditionType in pairs(conditions) do if player:getCondition(conditionType) then player:removeCondition(conditionType) @@ -58,18 +58,13 @@ function iceDeath.onStepIn(creature, item, position, fromPosition) if it then it:decay() end - player:addHealth((-player:getHealth() + 1)) + player:addHealth(-player:getHealth() + 1) player:sendTextMessage(MESSAGE_BEYOND_LAST, "You were killed by something evil and others.") - -- TODO parse active blessings and show that you didn't lose any blessings - player:sendTextMessage( - MESSAGE_BEYOND_LAST, - "You are still blessed with Wisdom of Solitude, Spark of the Phoenix,Fire of the Suns, \z - Spiritual Shielding, Embrace of Tibia, Heart of the Mountani, Blood of the Montain and Twist of Fate." - ) + player:sendTextMessage(MESSAGE_BEYOND_LAST, "You are still blessed with Wisdom of Solitude, Spark of the Phoenix, Fire of the Suns, Spiritual Shielding, Embrace of Tibia, Heart of the Mountain, Blood of the Mountain, and Twist of Fate.") player:sendTextMessage(MESSAGE_BEYOND_LAST, "You lost 0 experience and 0.00% of all of your skills.") player:sendTextMessage(MESSAGE_BEYOND_LAST, "You did not lose any items.") - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 3) - player:setStorageValue(Storage.CultsOfTibia.Barkless.AccessDoor, 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.AccessDoor, 1) player:sendTextMessage(MESSAGE_BEYOND_LAST, "The cold has all but disappeared from your body and you're getting warmer. You need to renew all preparations for purification.") player:sendFakeDeathWindow() else diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_looktype.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_looktype.lua index 021ccfc5aae..36a2eb09172 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_looktype.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_looktype.lua @@ -10,10 +10,10 @@ function looktype.onStepIn(creature, item, position, fromPosition) local secondCheck = Position(33128, 31885, 11) local thirdCheck = Position(33175, 31923, 12) if position == firstCheck or position == Position(firstCheck.x + 1, firstCheck.y, firstCheck.z) then - if player:getStorageValue(Storage.CultsOfTibia.Orcs.LookType) < 1 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType) < 1 then if creature:getOutfit().lookType == 5 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Due to the strength of an orc you are able to pass this rift.") - player:setStorageValue(Storage.CultsOfTibia.Orcs.LookType, 1) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType, 1) else player:teleportTo(fromPosition, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need the strength of an orc to pass this rift.") @@ -21,10 +21,10 @@ function looktype.onStepIn(creature, item, position, fromPosition) end end if position == secondCheck or position == Position(secondCheck.x + 1, secondCheck.y, secondCheck.z) then - if player:getStorageValue(Storage.CultsOfTibia.Orcs.LookType) < 2 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType) < 2 then if creature:getOutfit().lookType == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "With the help off the might of an orc warlod you are able to pass this rift.") - player:setStorageValue(Storage.CultsOfTibia.Orcs.LookType, 2) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType, 2) else player:teleportTo(fromPosition, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need the might of an orc warlod to pass this rift.") @@ -32,10 +32,10 @@ function looktype.onStepIn(creature, item, position, fromPosition) end end if position == thirdCheck or position == Position(thirdCheck.x + 1, thirdCheck.y, thirdCheck.z) or position == Position(thirdCheck.x + 2, thirdCheck.y, thirdCheck.z) then - if player:getStorageValue(Storage.CultsOfTibia.Orcs.LookType) < 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType) < 3 then if creature:getOutfit().lookType == 6 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "With the help of the wisdom of an orc shaman you are able to pass this rift.") - player:setStorageValue(Storage.CultsOfTibia.Orcs.LookType, 3) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Orcs.LookType, 3) else player:teleportTo(fromPosition, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need the wisdom of an orc shaman to pass this rift.") diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_river_teleport.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_river_teleport.lua index a6a7c3f92b8..2654c116985 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_river_teleport.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_river_teleport.lua @@ -12,12 +12,12 @@ function riverTeleport.onStepIn(creature, item, position, fromPosition) return false end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) < 7 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) < 7 then player:teleportTo(Position(33474, 32281, 10)) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) >= 7 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) >= 7 then player:teleportTo(Position(33479, 32235, 10)) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_sand_entrance.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_sand_entrance.lua index e8937a4bdf1..ad9557521a8 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_sand_entrance.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_sand_entrance.lua @@ -6,7 +6,7 @@ function sandEntrance.onStepIn(creature, item, position, fromPosition) return true end - if player:getStorageValue(Storage.CultsOfTibia.Life.Mission) < 1 and player:getStorageValue(Storage.CultsOfTibia.MotA.Mission) < 1 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Life.Mission) < 1 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.MotA.Mission) < 1 then player:teleportTo(fromPosition, true) player:sendCancelMessage("You can't go there yet.") end diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_tar.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_tar.lua index a19273791b5..144ece38ad4 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_tar.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_tar.lua @@ -5,21 +5,16 @@ local configQuest = { fromPos = Position(32737, 31489, 8), toPos = Position(32761, 31512, 8), effect = CONST_ME_HITBYFIRE, - firstSqm = Position(32750, 31508, 8), - secondSqm = Position(32746, 31469, 8), - storageBarkless = Storage.CultsOfTibia.Barkless.Tar, + firstTile = Position(32750, 31508, 8), + secondTile = Position(32746, 31469, 8), + storageBarkless = Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar, msgs = { - "As you enter the tar pits, you feel the heat around you rising dramatically. \z - Survive the heat long enough to prove worthy.", -- on enter + "As you enter the tar pits, you feel the heat around you rising dramatically. Survive the heat long enough to prove worthy.", -- on enter "Your body is heating up, the air around you is flickering.", -- 30/60 seconds - "The heat is now unbearable, the blood in your body feels like lava. \z - There's almost no strength left in you - act quickly!", -- 90 segunds - "Embrace the stigma of bad fortune. The tar does not feel so hot anymore. \z - You passed the tar trial.", -- step in the first tile - "Your body reacts to this strange green substance as you reach out to touch it. \z - You feel an urge for more of this energy.", -- step in the second tile - "The tar covering you has cooled down and tell off for the most part. \z - Your body is not heated up anymore.", -- there's no time to step + "The heat is now unbearable, the blood in your body feels like lava. There's almost no strength left in you - act quickly!", -- 90 seconds + "Embrace the stigma of bad fortune. The tar does not feel so hot anymore. You passed the tar trial.", -- step on the first tile + "Your body reacts to this strange green substance as you reach out to touch it. You feel an urge for more of this energy.", -- step on the second tile + "The tar covering you has cooled down and fell off for the most part. Your body is not heated up anymore.", -- didn't step in time }, }, ["acid"] = { @@ -28,62 +23,66 @@ local configQuest = { fromPos = Position(32647, 31479, 8), toPos = Position(32710, 31519, 8), effect = CONST_ME_YELLOW_RINGS, - firstSqm = Position(32680, 31485, 8), - secondSqm = Position(32664, 31504, 8), - storageBarkless = Storage.CultsOfTibia.Barkless.sulphur, + firstTile = Position(32680, 31485, 8), + secondTile = Position(32664, 31504, 8), + storageBarkless = Storage.Quest.U11_40.CultsOfTibia.Barkless.Sulphur, msgs = { "As you enter the sulphur pits, you feel the dry, burning vapours of the sulphur all around you. Prove worthy, survive the acid.", -- on enter - "The sulphur is burning your skin. You almost feel your body melting away in acid.", -- 30/60 segunds - "The acid burning is now unbearable, you skin feels like a sieve. \z - ]There's almost no strength left in you - act quickly!", -- 90 segunds - "Embrace the stigma of vanity. The sulphur does not burn your skin anymore. \z - You passed the trial.", -- step in the first tile - "You are now ready to prove your worth. \z - Take heart and cross the threshold of sulphur.", -- step in the second tile - "The acid covering you has cooled down and tell off for the most part. \z - Your body is not heated up anymore.", -- there's no time to step + "The sulphur is burning your skin. You almost feel your body melting away in acid.", -- 30/60 seconds + "The acid burning is now unbearable, your skin feels like a sieve. There's almost no strength left in you - act quickly!", -- 90 seconds + "Embrace the stigma of vanity. The sulphur does not burn your skin anymore. You passed the trial.", -- step on the first tile + "You are now ready to prove your worth. Take heart and cross the threshold of sulphur.", -- step on the second tile + "The acid covering you has cooled down and fell off for the most part. Your body is not heated up anymore.", -- didn't step in time }, }, } -function sendConditionCults(playerid, _type, fromPos, toPos, tempo) - local player = Player(playerid) +local function sendConditionCults(playerId, _type, fromPos, toPos, time) + local player = Player(playerId) if not player or not player:getPosition():isInRange(fromPos, toPos) then return false end - local inf = configQuest[_type] - tempo = tempo + 2 - if tempo == 30 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, inf.msgs[2]) - elseif tempo == 60 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, inf.msgs[2]) - elseif tempo >= 90 then - local stg = player:getStorageValue(inf.storageBarkless) < 0 and 0 or player:getStorageValue(inf.storageBarkless) - if stg < 3 and stg ~= 1 and stg ~= 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, inf.msgs[3]) - player:setStorageValue(inf.storageBarkless, 1) + local info = configQuest[_type] + time = time + 2 + if time == 30 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[2]) + elseif time == 60 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[2]) + elseif time >= 90 then + local stage = player:getStorageValue(info.storageBarkless) < 0 and 0 or player:getStorageValue(info.storageBarkless) + if stage < 3 and stage ~= 1 and stage ~= 2 then + if _type == "acid" and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar) ~= 3 then + return true + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[3]) + player:setStorageValue(info.storageBarkless, 1) + if _type == "fire" then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.TarAccessDoor, 1) + elseif _type == "acid" then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.SulphurAccessDoor, 1) + end end end - player:getPosition():sendMagicEffect(inf.effect) - addEvent(sendConditionCults, 2000, playerid, _type, fromPos, toPos, tempo) + player:getPosition():sendMagicEffect(info.effect) + addEvent(sendConditionCults, 2000, playerId, _type, fromPos, toPos, time) end -function passagemPiso1Piso2(playerid, info, tempo) - local player = Player(playerid) +function passageFloor1ToFloor2(playerId, info, time) + local player = Player(playerId) if not player then return true end - local stg = player:getStorageValue(info.storageBarkless) < 0 and 0 or player:getStorageValue(info.storageBarkless) - if tempo == 0 and stg < 3 then + local stage = player:getStorageValue(info.storageBarkless) < 0 and 0 or player:getStorageValue(info.storageBarkless) + if time == 0 and stage < 3 then player:setStorageValue(info.storageBarkless, 0) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, info.msgs[6]) return true end - if stg == 3 then + if stage == 3 then return true end - addEvent(passagemPiso1Piso2, 1000, playerid, info, tempo - 1) + addEvent(passageFloor1ToFloor2, 1000, playerId, info, time - 1) end local tar = MoveEvent() @@ -99,18 +98,15 @@ function tar.onStepIn(creature, item, position, fromPosition) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, value.msgs[1]) sendConditionCults(player:getId(), index, value.fromPos, value.toPos, 0) return true - elseif position:compare(value.firstSqm) and player:getStorageValue(value.storageBarkless) == 1 then - if player:getStorageValue(value.storageBarkless) ~= 1 then - return true - end + elseif position:compare(value.firstTile) and player:getStorageValue(value.storageBarkless) == 1 then player:setStorageValue(value.storageBarkless, 2) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, value.msgs[4]) - passagemPiso1Piso2(player:getId(), value, 60) - elseif position:compare(value.secondSqm) then + passageFloor1ToFloor2(player:getId(), value, 60) + elseif position:compare(value.secondTile) then if player:getStorageValue(value.storageBarkless) == 2 then player:setStorageValue(value.storageBarkless, 3) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.sulphur) == 3 and player:getStorageValue(Storage.CultsOfTibia.Barkless.Tar) == 3 then - player:setStorageValue(Storage.CultsOfTibia.Barkless.Mission, 2) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Sulphur) == 3 and player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar) == 3 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Mission, 2) end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, value.msgs[5]) end @@ -134,7 +130,7 @@ function tar.onStepOut(creature, item, position, fromPosition) if item:getActionId() == 5531 then if fromPosition.x == 32736 then player:getPosition():sendMagicEffect(CONST_ME_POFF) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.Tar) < 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Tar) < 3 then player:teleportTo(Position(32737, 31451, 8), true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not ready yet.") return false @@ -145,7 +141,7 @@ function tar.onStepOut(creature, item, position, fromPosition) if item:getActionId() == 5530 then if fromPosition.x == 32717 then player:getPosition():sendMagicEffect(CONST_ME_POFF) - if player:getStorageValue(Storage.CultsOfTibia.Barkless.sulphur) < 3 then + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Sulphur) < 3 then player:teleportTo(Position(32718, 31444, 8), true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not ready yet.") return false diff --git a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_task_teleport.lua b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_task_teleport.lua index acf48416449..3c254405b38 100644 --- a/data-otservbr-global/scripts/quests/cults_of_tibia/movements_task_teleport.lua +++ b/data-otservbr-global/scripts/quests/cults_of_tibia/movements_task_teleport.lua @@ -1,12 +1,12 @@ local setting = { [32415] = { - storage = Storage.CultsOfTibia.Humans.Decaying, + storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Decaying, max = 10, text = "You absorb the energetic remains of this decaying soul. Its power is very fragile and fleeting", effect = CONST_ME_GREEN_ENERGY_SPARK, }, [32414] = { - storage = Storage.CultsOfTibia.Humans.Vaporized, + storage = Storage.Quest.U11_40.CultsOfTibia.Humans.Vaporized, max = 10, text = "You absorb the energetic remains of this whitering soul. Its power is very fragile and fleeting.", effect = CONST_ME_BLUE_ENERGY_SPARK, @@ -21,11 +21,11 @@ function taskTeleport.onStepIn(creature, item, position, fromPosition) return true end - if player:getStorageValue(Storage.CultsOfTibia.Questline) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Questline, 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Questline) < 1 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Questline, 1) end - if player:getStorageValue(Storage.CultsOfTibia.Humans.Mission) < 1 then - player:setStorageValue(Storage.CultsOfTibia.Humans.Mission, 1) + if player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.Mission) < 1 then + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Humans.Mission, 1) end for index, value in pairs(setting) do diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump.lua index 64875337f37..85d4abb87f6 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump.lua @@ -15,8 +15,8 @@ function dangerousDepthPump.onUse(player, item) for _, spectator in pairs(spectators) do if spectator:isPlayer() then local playerSpectator = spectator - if playerSpectator:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneVI) ~= 1 then - playerSpectator:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneVI, 1) + if playerSpectator:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI) ~= 1 then + playerSpectator:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI, 1) end end end @@ -33,8 +33,8 @@ function dangerousDepthPump.onUse(player, item) for _, spectator in pairs(spectators) do if spectator:isPlayer() then local playerSpectator = spectator - if playerSpectator:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneV) ~= 1 then - playerSpectator:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneV, 1) + if playerSpectator:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV) ~= 1 then + playerSpectator:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV, 1) end end end @@ -51,8 +51,8 @@ function dangerousDepthPump.onUse(player, item) for _, spectator in pairs(spectators) do if spectator:isPlayer() then local playerSpectator = spectator - if playerSpectator:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneIV) ~= 1 then - playerSpectator:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneIV, 1) + if playerSpectator:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV) ~= 1 then + playerSpectator:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV, 1) end end end diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump_achievements.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump_achievements.lua index ad6b13cda90..6b3c2fe73c5 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump_achievements.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_crude_lava_pump_achievements.lua @@ -32,30 +32,30 @@ function dangerousDepthAchievements.onUse(player, item) local WarzoneVI = Position(33685, 32304, 15) if positionItem == WarzoneIV then -- Warzone VI - if player:getStorageValue(Storage.DangerousDepths.Bosses.TheBaronFromBelowAchiev) < 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheBaronFromBelowAchiev) < 1 then player:addAchievement("Buried the Baron") - player:setStorageValue(Storage.DangerousDepths.Bosses.TheBaronFromBelowAchiev, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheBaronFromBelowAchiev, 1) end end if positionItem == WarzoneV then -- Warzone V - if player:getStorageValue(Storage.DangerousDepths.Bosses.TheCountOfTheCoreAchiev) < 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheCountOfTheCoreAchiev) < 1 then player:addAchievement("His Days are Counted") - player:setStorageValue(Storage.DangerousDepths.Bosses.TheCountOfTheCoreAchiev, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheCountOfTheCoreAchiev, 1) end end if positionItem == WarzoneVI then -- Warzone IV - if player:getStorageValue(Storage.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev) < 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev) < 1 then player:addAchievement("Duked It Out") - player:setStorageValue(Storage.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev, 1) end end - if player:getStorageValue(Storage.DangerousDepths.Bosses.LastAchievement) < 1 then - if player:getStorageValue(Storage.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev) == 1 and player:getStorageValue(Storage.DangerousDepths.Bosses.TheBaronFromBelowAchiev) == 1 and player:getStorageValue(Storage.DangerousDepths.Bosses.TheCountOfTheCoreAchiev) == 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.LastAchievement) < 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheDukeOfTheDepthsAchiev) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheBaronFromBelowAchiev) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.TheCountOfTheCoreAchiev) == 1 then player:addAchievement("Death in the Depths") - player:setStorageValue(Storage.DangerousDepths.Bosses.LastAchievement, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Bosses.LastAchievement, 1) end end return true diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_chart.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_chart.lua index f3f74036171..f6dbddb003f 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_chart.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_chart.lua @@ -13,51 +13,51 @@ function dangerousDepthChart.onUse(player, item, isHotkey) return true end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Charting) == 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Charting) == 1 then if player:getPosition():isInRange(config.OldGate.fromPosition, config.OldGate.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.OldGate) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.OldGate, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.OldGate) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.OldGate, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, an ancient gate.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.LostRuin.fromPosition, config.LostRuin.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LostRuin) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LostRuin, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LostRuin) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LostRuin, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, a small ruin.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.TheGaze.fromPosition, config.TheGaze.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.TheGaze) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.TheGaze, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TheGaze) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.TheGaze, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, resembling a stone face.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.Outpost.fromPosition, config.Outpost.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Outpost) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.Outpost, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Outpost) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Outpost, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, an outpost.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.Bastion.fromPosition, config.Bastion.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Bastion) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.Bastion, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Bastion) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Bastion, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, a bastion.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.BrokenTower.fromPosition, config.BrokenTower.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.BrokenTower) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.BrokenTower, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.ChartingCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.BrokenTower) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.BrokenTower, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.ChartingCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You charted the location and dimensions of a strange structure, a broken tower.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end @@ -66,5 +66,5 @@ function dangerousDepthChart.onUse(player, item, isHotkey) return true end -dangerousDepthChart:id(31931) +dangerousDepthChart:id(27308) dangerousDepthChart:register() diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_items.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_items.lua index 4589b865066..bffb5a5bcf5 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_items.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_items.lua @@ -1,22 +1,24 @@ local dangerousDepthItems = Action() + function dangerousDepthItems.onUse(player, item) - if item:getUniqueId() == 57235 then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartPaper) == 1 then -- Permissão para usar o baú == 1 then - player:addItem(31931, 1) + if item.uid == 57235 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartPaper) == 1 then + player:addItem(27308, 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a gnome charts.") - player:setStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartPaper, 2) - elseif player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartPaper) == 2 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartPaper, 2) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartPaper) == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this item again.") end - elseif item:getUniqueId() == 57236 then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartChest) == 1 then -- Permissão para usar o baú == 1 then - player:addItem(31930, 1) + elseif item.uid == 57236 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartChest) == 1 then + player:addItem(27307, 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a gnome trignometre.") - player:setStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartChest, 2) - elseif player:getStorageValue(Storage.DangerousDepths.Gnomes.GnomeChartChest) == 2 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartChest, 2) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomeChartChest) == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "It is empty.") end end + return true end diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_trignometre.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_trignometre.lua index 458e9f67c2e..baf96e52253 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_trignometre.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnome_trignometre.lua @@ -11,43 +11,43 @@ function dangerousDepthTrignometre.onUse(player, item, isHotkey) if not player then return true end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Measurements) == 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Measurements) == 1 then if player:getPosition():isInRange(config.locationA.fromPosition, config.locationA.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationA) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationA, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationA) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationA, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You probed the location successfully.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.locationB.fromPosition, config.locationB.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationB) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationB, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationB) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationB, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You probed the location successfully.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.locationC.fromPosition, config.locationC.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationC) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationC, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationC) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationC, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You probed the location successfully.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.locationD.fromPosition, config.locationD.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationD) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationD, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationD) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationD, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You probed the location successfully.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end end if player:getPosition():isInRange(config.locationE.fromPosition, config.locationE.toPosition) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationE) < 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationE, 1) - player:setStorageValue(Storage.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.DangerousDepths.Gnomes.LocationCount) + 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationE) < 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationE, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.LocationCount) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You probed the location successfully.") player:getPosition():sendMagicEffect(CONST_ME_HITAREA) end @@ -56,5 +56,5 @@ function dangerousDepthTrignometre.onUse(player, item, isHotkey) return true end -dangerousDepthTrignometre:id(31930) +dangerousDepthTrignometre:id(27307) dangerousDepthTrignometre:register() diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_chest.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_chest.lua index 6219bb88ac3..418d1d16c9b 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_chest.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_chest.lua @@ -1,10 +1,11 @@ local dangerousDepthChest = Action() + function dangerousDepthChest.onUse(player, item) - if player:getStorageValue(Storage.DangerousDepths.Scouts.GnomishChest) == 1 then - player:addItem(30733, 1) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.GnomishChest) == 1 then + player:addItem(27498, 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found gnomish pesticides.") - player:setStorageValue(Storage.DangerousDepths.Scouts.GnomishChest, 2) - elseif player:getStorageValue(Storage.DangerousDepths.Scouts.GnomishChest) == 2 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.GnomishChest, 2) + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.GnomishChest) == 2 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "It is empty.") end return true diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_pesticide.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_pesticide.lua index a256e3bf6c6..55aae368926 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_pesticide.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_gnomish_pesticide.lua @@ -1,4 +1,5 @@ local dangerousDepthPesticide = Action() + function dangerousDepthPesticide.onUse(player, item, fromPosition, target, toPosition, isHotkey) if not player then return true @@ -17,15 +18,15 @@ function dangerousDepthPesticide.onUse(player, item, fromPosition, target, toPos local posTarget = target:getPosition() if target:getId() == corpseId then - if player:getStorageValue(Storage.DangerousDepths.Scouts.Diremaw) == 1 and player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount) < 20 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Diremaw) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount) < 20 then if r <= 50 then posTarget:sendMagicEffect(CONST_ME_POISONAREA) local diremaw = Game.createMonster("Diremaw", target:getPosition()) - player:setStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount, player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount) + 1) target:transform(30730) else posTarget:sendMagicEffect(CONST_ME_POISONAREA) - player:setStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount, player:getStorageValue(Storage.DangerousDepths.Scouts.DiremawsCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.DiremawsCount) + 1) target:transform(30730) end end @@ -37,5 +38,5 @@ function dangerousDepthPesticide.onUse(player, item, fromPosition, target, toPos return true end -dangerousDepthPesticide:id(30733) +dangerousDepthPesticide:id(27498) dangerousDepthPesticide:register() diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_lever_barrel.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_lever_barrel.lua index 327878284a0..1a478e3200e 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_lever_barrel.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_lever_barrel.lua @@ -5,31 +5,31 @@ local transformid = { local config = { first = { - [1] = { fromPosition = Position(33877, 32060, 14), toPosition = Position(33888, 32068, 14), stgRoom = Storage.DangerousDepths.Scouts.FirstBarrel }, + [1] = { fromPosition = Position(33877, 32060, 14), toPosition = Position(33888, 32068, 14), stgRoom = Storage.Quest.U11_50.DangerousDepths.Scouts.FirstBarrel }, }, second = { - [1] = { fromPosition = Position(33906, 32026, 14), toPosition = Position(33916, 32037, 14), stgRoom = Storage.DangerousDepths.Scouts.SecondBarrel }, + [1] = { fromPosition = Position(33906, 32026, 14), toPosition = Position(33916, 32037, 14), stgRoom = Storage.Quest.U11_50.DangerousDepths.Scouts.SecondBarrel }, }, third = { - [1] = { fromPosition = Position(33865, 32009, 14), toPosition = Position(33874, 32020, 14), stgRoom = Storage.DangerousDepths.Scouts.ThirdBarrel }, + [1] = { fromPosition = Position(33865, 32009, 14), toPosition = Position(33874, 32020, 14), stgRoom = Storage.Quest.U11_50.DangerousDepths.Scouts.ThirdBarrel }, }, fourth = { - [1] = { fromPosition = Position(33837, 31984, 14), toPosition = Position(33852, 31991, 14), stgRoom = Storage.DangerousDepths.Scouts.FourthBarrel }, + [1] = { fromPosition = Position(33837, 31984, 14), toPosition = Position(33852, 31991, 14), stgRoom = Storage.Quest.U11_50.DangerousDepths.Scouts.FourthBarrel }, }, fifth = { - [1] = { fromPosition = Position(33923, 31982, 14), toPosition = Position(33942, 31998, 14), stgRoom = Storage.DangerousDepths.Scouts.FifthBarrel }, + [1] = { fromPosition = Position(33923, 31982, 14), toPosition = Position(33942, 31998, 14), stgRoom = Storage.Quest.U11_50.DangerousDepths.Scouts.FifthBarrel }, }, } -local function checarPos(item) +local function checkPos(item) for _, info1 in pairs(config.first) do local fromPos, toPos, stgRoom = info1.fromPosition, info1.toPosition, info1.stgRoom if item:getPosition():isInRange(fromPos, toPos) then - local stgbarrel = item:getCustomAttribute(Storage.DangerousDepths.Scouts.Barrel) or -1 - local player = Player(stgbarrel) + local stgBarrel = item:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + local player = Player(stgBarrel) if player then if player:getStorageValue(stgRoom) < 1 then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + 1) player:setStorageValue(stgRoom, 1) end end @@ -38,11 +38,11 @@ local function checarPos(item) for _, info2 in pairs(config.second) do local fromPos, toPos, stgRoom = info2.fromPosition, info2.toPosition, info2.stgRoom if item:getPosition():isInRange(fromPos, toPos) then - local stgbarrel = item:getCustomAttribute(Storage.DangerousDepths.Scouts.Barrel) or -1 - local player = Player(stgbarrel) + local stgBarrel = item:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + local player = Player(stgBarrel) if player then if player:getStorageValue(stgRoom) < 1 then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + 1) player:setStorageValue(stgRoom, 1) end end @@ -51,11 +51,11 @@ local function checarPos(item) for _, info3 in pairs(config.third) do local fromPos, toPos, stgRoom = info3.fromPosition, info3.toPosition, info3.stgRoom if item:getPosition():isInRange(fromPos, toPos) then - local stgbarrel = item:getCustomAttribute(Storage.DangerousDepths.Scouts.Barrel) or -1 - local player = Player(stgbarrel) + local stgBarrel = item:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + local player = Player(stgBarrel) if player then if player:getStorageValue(stgRoom) < 1 then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + 1) player:setStorageValue(stgRoom, 1) end end @@ -64,11 +64,11 @@ local function checarPos(item) for _, info4 in pairs(config.fourth) do local fromPos, toPos, stgRoom = info4.fromPosition, info4.toPosition, info4.stgRoom if item:getPosition():isInRange(fromPos, toPos) then - local stgbarrel = item:getCustomAttribute(Storage.DangerousDepths.Scouts.Barrel) or -1 - local player = Player(stgbarrel) + local stgBarrel = item:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + local player = Player(stgBarrel) if player then if player:getStorageValue(stgRoom) < 1 then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + 1) player:setStorageValue(stgRoom, 1) end end @@ -77,11 +77,11 @@ local function checarPos(item) for _, info5 in pairs(config.fifth) do local fromPos, toPos, stgRoom = info5.fromPosition, info5.toPosition, info5.stgRoom if item:getPosition():isInRange(fromPos, toPos) then - local stgbarrel = item:getCustomAttribute(Storage.DangerousDepths.Scouts.Barrel) or -1 - local player = Player(stgbarrel) + local stgBarrel = item:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + local player = Player(stgBarrel) if player then if player:getStorageValue(stgRoom) < 1 then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount, player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + 1) player:setStorageValue(stgRoom, 1) end end @@ -93,57 +93,55 @@ local function explode(item) local position = item:getPosition() local fromPosition = Position(position.x - 6, position.y - 6, position.z) local toPosition = Position(position.x + 6, position.y + 6, position.z) + local c = Game.getPlayers()[1] addEvent(function() for x = fromPosition.x, toPosition.x do for y = fromPosition.y, toPosition.y do for z = fromPosition.z, toPosition.z do - Position(x, y, z):sendMagicEffect(CONST_ME_FIREAREA) + if Tile(Position(x, y, z)) then + if Tile(Position(x, y, z)) then + local posEffect = Tile(Position(x, y, z)):getPosition() + local creature = Tile(Position(x, y, z)):getTopCreature() + posEffect:sendMagicEffect(CONST_ME_FIREAREA) + end + end end end end - checarPos(item) + checkPos(item) + c:say("KABOOM!!", TALKTYPE_MONSTER_SAY, false, false, position) if item then item:remove() end end, 2 * 1000) - item:transform(32401) + item:transform(27491) + c:say("Tsssss...!", TALKTYPE_MONSTER_SAY, false, false, position) end local dangerousDepthLever = Action() + function dangerousDepthLever.onUse(player, item) if not player then return true end local posBarrel = Position(33838, 32077, 14) - local stgCount = player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelCount) - local BarrelTimer = player:getStorageValue(Storage.DangerousDepths.Scouts.BarrelTimer) + local stgCount = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelCount) + local barrelTimer = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelTimer) if item:getId() == 2772 then - if player:getStorageValue(Storage.DangerousDepths.Scouts.Growth) == 1 and stgCount < 5 and BarrelTimer <= 0 then - local barrel = Game.createItem(27492, 1, posBarrel) - if not barrel then - return false - end - barrel:setCustomAttribute(Storage.DangerousDepths.Scouts.Barrel, player:getId()) - - addEvent(function(pos, pid) - local tile = Tile(pos) - if tile then - local barrel = tile:getItemById(27492) - if barrel then - explode(barrel) - end - end - local player = Player(pid) - if player then - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelTimer, 0) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Growth) == 1 and stgCount < 5 and barrelTimer <= 0 then + local Barrel = Game.createItem(27492, 1, posBarrel) + local stgBarrel = Barrel:getCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel) or -1 + Barrel:setCustomAttribute(Storage.Quest.U11_50.DangerousDepths.Scouts.Barrel, player:getId()) + addEvent(function() + if Barrel then + explode(Barrel) end - end, 2 * 60 * 1000, posBarrel, player:getId()) - - --Time is set to 0 when barrel explodes - player:setStorageValue(Storage.DangerousDepths.Scouts.BarrelTimer, os.time() + 2 * 60) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelTimer, 0) + end, 2 * 60 * 1000) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.BarrelTimer, os.time() + 2 * 60) end end item:transform(transformid[item:getId()]) diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_using_crystals.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_using_crystals.lua index 84dc7e433fa..6f134dab02d 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_using_crystals.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_using_crystals.lua @@ -420,14 +420,14 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi local targetPosition = target:getPosition() if targetPosition == WarzoneIV and target:getId() == geodeId then -- Warzone 4 BOSS!!! - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV) < 30 then + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV) < 30 then targetPosition:sendMagicEffect(CONST_ME_HITAREA) item:remove(1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV) < 0 then - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV, 0) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV) < 0 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV, 0) end - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV, Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV) + 1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneIV) == 30 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV, Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV) + 1) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV) == 30 then local spectators = Game.getSpectators(targetPosition, false, true, 3, 3, 3, 3) for _, spectator in pairs(spectators) do if spectator:isPlayer() then @@ -445,7 +445,7 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi Game.createItem(388, 1, Position(33460, 32267, 15)) end end, 8 * 1000) - addEvent(clearForgotten, 30 * 60 * 1000, Position(33638, 32291, 15), Position(33675, 32313, 15), Position(33462, 32267, 15), GlobalStorage.DangerousDepths.Geodes.WarzoneIV) + addEvent(clearForgotten, 30 * 60 * 1000, Position(33638, 32291, 15), Position(33675, 32313, 15), Position(33462, 32267, 15), Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneIV) startWarzoneIV() end end @@ -455,14 +455,14 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi end if targetPosition == WarzoneV and target:getId() == geodeId then -- Warzone 5 BOSS!!! - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV) < 30 then + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV) < 30 then targetPosition:sendMagicEffect(CONST_ME_HITAREA) item:remove(1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV) < 0 then - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV, 0) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV) < 0 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV, 0) end - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV, Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV) + 1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneV) == 30 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV, Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV) + 1) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV) == 30 then local spectators = Game.getSpectators(targetPosition, false, true, 3, 3, 3, 3) for _, spectator in pairs(spectators) do if spectator:isPlayer() then @@ -480,7 +480,7 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi Game.createItem(388, 1, Position(33324, 32109, 15)) end end, 8 * 1000) - addEvent(clearForgotten, 30 * 60 * 1000, Position(33668, 32310, 15), Position(33695, 32343, 15), Position(33323, 32111, 15), GlobalStorage.DangerousDepths.Geodes.WarzoneV) + addEvent(clearForgotten, 30 * 60 * 1000, Position(33668, 32310, 15), Position(33695, 32343, 15), Position(33323, 32111, 15), Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneV) startWarzoneV() end end @@ -490,14 +490,14 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi end if targetPosition == WarzoneVI and target:getId() == geodeId then -- Warzone 6 BOSS!!! - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI) < 30 then + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI) < 30 then targetPosition:sendMagicEffect(CONST_ME_HITAREA) item:remove(1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI) < 0 then - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI, 0) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI) < 0 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI, 0) end - Game.setStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI, Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI) + 1) - if Game.getStorageValue(GlobalStorage.DangerousDepths.Geodes.WarzoneVI) == 30 then + Game.setStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI, Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI) + 1) + if Game.getStorageValue(Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI) == 30 then local spectators = Game.getSpectators(targetPosition, false, true, 3, 3, 3, 3) for _, spectator in pairs(spectators) do if spectator:isPlayer() then @@ -515,7 +515,7 @@ function dangerousDepthCrystals.onUse(player, item, fromPosition, target, toPosi Game.createItem(388, 1, Position(33275, 32316, 15)) end end, 8 * 1000) - addEvent(clearForgotten, 30 * 60 * 1000, Position(33684, 32293, 15), Position(33724, 32314, 15), Position(33275, 32318, 15), GlobalStorage.DangerousDepths.Geodes.WarzoneVI) + addEvent(clearForgotten, 30 * 60 * 1000, Position(33684, 32293, 15), Position(33724, 32314, 15), Position(33275, 32318, 15), Storage.Quest.U11_50.DangerousDepths.Geodes.WarzoneVI) startWarzoneVI() end end diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_warzone_crystals.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_warzone_crystals.lua index 910b900c4da..64ebb40f399 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_warzone_crystals.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_warzone_crystals.lua @@ -2,28 +2,28 @@ local crystalDuration = 5 * 60 -- 5 minutes local crystals = { -- Warzone IV - [57350] = Storage.DangerousDepths.Crystals.WarzoneVI.MediumCrystal1, - [57351] = Storage.DangerousDepths.Crystals.WarzoneVI.BigCrystal1, - [57352] = Storage.DangerousDepths.Crystals.WarzoneVI.BigCrystal2, - [57353] = Storage.DangerousDepths.Crystals.WarzoneVI.MediumCrystal2, - [57354] = Storage.DangerousDepths.Crystals.WarzoneVI.SmallCrystal1, - [57355] = Storage.DangerousDepths.Crystals.WarzoneVI.SmallCrystal2, + [57350] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.MediumCrystal1, + [57351] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.BigCrystal1, + [57352] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.BigCrystal2, + [57353] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.MediumCrystal2, + [57354] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.SmallCrystal1, + [57355] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneVI.SmallCrystal2, -- Warzone V - [57356] = Storage.DangerousDepths.Crystals.WarzoneV.BigCrystal1, - [57357] = Storage.DangerousDepths.Crystals.WarzoneIV.MediumCrystal1, - [57358] = Storage.DangerousDepths.Crystals.WarzoneV.BigCrystal2, - [57359] = Storage.DangerousDepths.Crystals.WarzoneIV.MediumCrystal2, - [57360] = Storage.DangerousDepths.Crystals.WarzoneV.SmallCrystal1, - [57361] = Storage.DangerousDepths.Crystals.WarzoneV.SmallCrystal2, + [57356] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneV.BigCrystal1, + [57357] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.MediumCrystal1, + [57358] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneV.BigCrystal2, + [57359] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.MediumCrystal2, + [57360] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneV.SmallCrystal1, + [57361] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneV.SmallCrystal2, -- Warzone IV - [57362] = Storage.DangerousDepths.Crystals.WarzoneIV.BigCrystal1, - [57363] = Storage.DangerousDepths.Crystals.WarzoneIV.MediumCrystal1, - [57364] = Storage.DangerousDepths.Crystals.WarzoneIV.BigCrystal2, - [57365] = Storage.DangerousDepths.Crystals.WarzoneIV.MediumCrystal2, - [57366] = Storage.DangerousDepths.Crystals.WarzoneIV.SmallCrystal1, - [57367] = Storage.DangerousDepths.Crystals.WarzoneIV.SmallCrystal2, + [57362] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.BigCrystal1, + [57363] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.MediumCrystal1, + [57364] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.BigCrystal2, + [57365] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.MediumCrystal2, + [57366] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.SmallCrystal1, + [57367] = Storage.Quest.U11_50.DangerousDepths.Crystals.WarzoneIV.SmallCrystal2, } local crystalsChance = { diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/actions_wooden_trash.lua b/data-otservbr-global/scripts/quests/dangerous_depth/actions_wooden_trash.lua index 15aa8ec6f4b..0ca92bacb45 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/actions_wooden_trash.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/actions_wooden_trash.lua @@ -1,12 +1,13 @@ local dangerousDepthWooden = Action() + function dangerousDepthWooden.onUse(creature, item) if not creature or not creature:isPlayer() then return true end local r = math.random(1, 100) - local stgValueP = creature:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) + local stgValueP = creature:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) - if creature:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1 and stgValueP < 3 then + if creature:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 1 and stgValueP < 3 then if r <= 25 then creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You started an escort, get your prisoner to the dwarf outpost!") local prisoner = Game.createMonster("Captured Dwarf", item:getPosition()) diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/creaturescripts_lost_exile_task.lua b/data-otservbr-global/scripts/quests/dangerous_depth/creaturescripts_lost_exile_task.lua index 24abf74281c..2802324b3c3 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/creaturescripts_lost_exile_task.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/creaturescripts_lost_exile_task.lua @@ -1,40 +1,62 @@ local fromPos = Position(33768, 32227, 14) -local toPos = Position(33781, 32249, 14) +local toPos = Position(33851, 32352, 14) +local radius = 10 local lostExileKill = CreatureEvent("LastExileDeath") + function lostExileKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) + local function isMakeshiftHomeNearby(creature) + local creaturePosition = creature:getPosition() + local spectators = Game.getSpectators(creaturePosition, false, false, radius, radius, radius, radius) -- Busca criaturas em torno da posição da morte + + for _, spectator in ipairs(spectators) do + if spectator:isMonster() and spectator:getName():lower() == "makeshift home" then + return true + end + end + return false + end + onDeathForParty(creature, mostDamageKiller, function(creature, player) - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Home) ~= 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) ~= 1 then return end + if not creature:getPosition():isInRange(fromPos, toPos) then return end - local storage = player:getStorageValue(Storage.DangerousDepths.Dwarves.LostExiles) + + if isMakeshiftHomeNearby(creature) then + return + end + + local storage = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles) if storage < 20 then if storage < 0 then - player:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles, 1) end - player:setStorageValue(Storage.DangerousDepths.Dwarves.LostExiles, storage + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.LostExiles, storage + 1) end end) + return true end lostExileKill:register() local wormKill = CreatureEvent("WarzoneWormDeath") + function wormKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) - local storage = mostDamageKiller:getStorageValue(Storage.DangerousDepths.Dwarves.Organisms) + local storage = mostDamageKiller:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms) onDeathForParty(creature, mostDamageKiller, function(creature, player) - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Subterranean) ~= 1 then + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Subterranean) ~= 1 then return end if storage < 50 then if storage < 0 then - player:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms, 1) end - player:setStorageValue(Storage.DangerousDepths.Dwarves.Organisms, storage + 1) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Organisms, storage + 1) end end) @@ -44,6 +66,7 @@ end wormKill:register() local makeshiftKill = CreatureEvent("MakeshiftHomeDeath") + function makeshiftKill.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) local woodenTrash = Game.createItem(398, 1, creature:getPosition()) woodenTrash:setActionId(57233) diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/movements_energy_entrance.lua b/data-otservbr-global/scripts/quests/dangerous_depth/movements_energy_entrance.lua index c4d76a05488..ebfd9a1f574 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/movements_energy_entrance.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/movements_energy_entrance.lua @@ -14,8 +14,14 @@ function energyEntrance.onStepIn(creature, item, position, fromPosition, toPosit if not player then return true end + + local function hasWarzoneAccess() + return player:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.Warzone1Access) == 1 and player:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.Warzone2Access) == 1 and player:getStorageValue(Storage.Quest.U9_60.BigfootsBurden.Warzone3Access) == 1 + end + if player:getPosition() == Position(33831, 32138, 14) then - if player:getStorageValue(Storage.DangerousDepths.Scouts.Status) >= -50 then + local status = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Scouts.Points) + if (hasWarzoneAccess() and status >= 10) or (not hasWarzoneAccess() and status >= 15) then player:teleportTo(Position(34023, 32037, 14)) else player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this portal yet.") @@ -23,10 +29,9 @@ function energyEntrance.onStepIn(creature, item, position, fromPosition, toPosit end elseif player:getPosition() == Position(34021, 32037, 14) then player:teleportTo(Position(33831, 32141, 14)) - end - - if player:getPosition() == Position(33784, 32205, 14) then - if player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) >= -50 then + elseif player:getPosition() == Position(33784, 32205, 14) then + local status = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Points) + if (hasWarzoneAccess() and status >= 10) or (not hasWarzoneAccess() and status >= 15) then player:teleportTo(Position(33921, 32401, 14)) else player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this portal yet.") @@ -34,10 +39,9 @@ function energyEntrance.onStepIn(creature, item, position, fromPosition, toPosit end elseif player:getPosition() == Position(33921, 32402, 14) then player:teleportTo(Position(33782, 32205, 14)) - end - - if player:getPosition() == Position(33829, 32187, 14) then - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) >= -50 then + elseif player:getPosition() == Position(33829, 32187, 14) then + local status = player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Points) + if (hasWarzoneAccess() and status >= 10) or (not hasWarzoneAccess() and status >= 15) then player:teleportTo(Position(33982, 32236, 14)) else player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this portal yet.") @@ -46,6 +50,7 @@ function energyEntrance.onStepIn(creature, item, position, fromPosition, toPosit elseif player:getPosition() == Position(33982, 32234, 14) then player:teleportTo(Position(33829, 32186, 14)) end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true @@ -54,4 +59,5 @@ end for index, value in pairs(positions) do energyEntrance:position(value) end + energyEntrance:register() diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnome_ordnance.lua b/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnome_ordnance.lua index c74f3db575c..555ba543a26 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnome_ordnance.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnome_ordnance.lua @@ -6,8 +6,8 @@ function gnomeOrdnance.onStepIn(creature, position, fromPosition, toPosition) return true end - if player:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 1 then - player:setStorageValue(Storage.DangerousDepths.Gnomes.Ordnance, 2) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 1 then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance, 2) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You started an escort, get everyone to safety!") end return true diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnomes_ordnance_end.lua b/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnomes_ordnance_end.lua index 3bb8c2f8c9e..cda301170c1 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnomes_ordnance_end.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/movements_gnomes_ordnance_end.lua @@ -17,9 +17,9 @@ function gnomesOrdnanceEnd.onStepIn(creature, position, fromPosition, toPosition local c = Tile(Position(x, y, z)):getTopCreature() if c then if c:isPlayer() then - if c:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 2 then - if c:getStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount) < 5 then - c:setStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount, c:getStorageValue(Storage.DangerousDepths.Gnomes.GnomesCount) + 1) + if c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 2 then + if c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount) < 5 then + c:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount, c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.GnomesCount) + 1) c:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your escort has end.") end end @@ -41,9 +41,9 @@ function gnomesOrdnanceEnd.onStepIn(creature, position, fromPosition, toPosition local c = Tile(Position(x, y, z)):getTopCreature() if c then if c:isPlayer() then - if c:getStorageValue(Storage.DangerousDepths.Gnomes.Ordnance) == 2 then - if c:getStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount) < 3 then - c:setStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount, c:getStorageValue(Storage.DangerousDepths.Gnomes.CrawlersCount) + 1) + if c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.Ordnance) == 2 then + if c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount) < 3 then + c:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount, c:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Gnomes.CrawlersCount) + 1) c:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your escort has end.") end end diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/movements_lost_exiles.lua b/data-otservbr-global/scripts/quests/dangerous_depth/movements_lost_exiles.lua index 2c53dbaba75..5dbb5225fc9 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/movements_lost_exiles.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/movements_lost_exiles.lua @@ -17,9 +17,9 @@ function lostExiles.onStepIn(creature, position, fromPosition, toPosition) local creature = Tile(Position(x, y, z)):getTopCreature() if creature then if creature:isPlayer() then - if creature:getStorageValue(Storage.DangerousDepths.Dwarves.Home) == 1 then - if creature:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) < 3 then - creature:setStorageValue(Storage.DangerousDepths.Dwarves.Prisoners, creature:getStorageValue(Storage.DangerousDepths.Dwarves.Prisoners) + 1) + if creature:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Home) == 1 then + if creature:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) < 3 then + creature:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners, creature:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Dwarves.Prisoners) + 1) creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your escort has end.") end end diff --git a/data-otservbr-global/scripts/quests/dangerous_depth/movements_warzone_entrance.lua b/data-otservbr-global/scripts/quests/dangerous_depth/movements_warzone_entrance.lua index 83120868640..ecb404fe5ef 100644 --- a/data-otservbr-global/scripts/quests/dangerous_depth/movements_warzone_entrance.lua +++ b/data-otservbr-global/scripts/quests/dangerous_depth/movements_warzone_entrance.lua @@ -8,65 +8,54 @@ function warzoneEntrance.onStepIn(creature, item, position, fromPosition, toPosi local warzoneVI = Position(33367, 32307, 15) if item:getPosition() == Position(33829, 32128, 14) then - if player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneVI) == 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneVI) <= os.time() then - player:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneVI, 0) - player:setStorageValue(Storage.DangerousDepths.Scouts.Status, player:getStorageValue(Storage.DangerousDepths.Scouts.Status) - 10) - player:setStorageValue(Storage.DangerousDepths.Access.TimerWarzoneVI, os.time() + 8 * 60 * 60) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneVI) <= os.time() then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneVI, os.time() + 8 * 60 * 60) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone (you can enter freely for 8 hours from now).") player:teleportTo(warzoneVI) - elseif player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneVI) ~= 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneVI) <= os.time() then + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneVI) ~= 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneVI) <= os.time() then player:teleportTo(Position(fromPosition.x + 1, fromPosition.y, fromPosition.z)) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "You cannot enter this warzone. \z - The enemy still pumps lava into this area. Find a way to stop the pumps!" - ) - elseif player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneVI) > os.time() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot enter this warzone. The enemy still pumps lava into this area. Find a way to stop the pumps!") + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneVI) > os.time() then player:teleportTo(warzoneVI) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone.") end end + local warzoneV = Position(33208, 32119, 15) if item:getPosition() == Position(33777, 32192, 14) then - if player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneV) == 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneV) <= os.time() then - player:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneV, 0) - player:setStorageValue(Storage.DangerousDepths.Dwarves.Status, player:getStorageValue(Storage.DangerousDepths.Dwarves.Status) - 10) - player:setStorageValue(Storage.DangerousDepths.Access.TimerWarzoneV, os.time() + 8 * 60 * 60) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneV) <= os.time() then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneV, os.time() + 8 * 60 * 60) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone (you can enter freely for 8 hours from now).") player:teleportTo(warzoneV) - elseif player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneV) ~= 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneV) <= os.time() then + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneV) ~= 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneV) <= os.time() then player:teleportTo(Position(fromPosition.x, fromPosition.y + 1, fromPosition.z)) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "You cannot enter this warzone. \z - The enemy still pumps lava into this area. Find a way to stop the pumps!" - ) - elseif player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneV) > os.time() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot enter this warzone.The enemy still pumps lava into this area. Find a way to stop the pumps!") + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneV) > os.time() then player:teleportTo(warzoneV) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone.") end end + local warzoneIV = Position(33534, 32184, 15) if item:getPosition() == Position(33827, 32172, 14) then - if player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneIV) == 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneIV) <= os.time() then - player:setStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneIV, 0) - player:setStorageValue(Storage.DangerousDepths.Gnomes.Status, player:getStorageValue(Storage.DangerousDepths.Gnomes.Status) - 10) - player:setStorageValue(Storage.DangerousDepths.Access.TimerWarzoneIV, os.time() + 8 * 60 * 60) + if player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV) == 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneIV) <= os.time() then + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV, 0) + player:setStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneIV, os.time() + 8 * 60 * 60) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone (you can enter freely for 8 hours from now).") player:teleportTo(warzoneIV) - elseif player:getStorageValue(Storage.DangerousDepths.Access.LavaPumpWarzoneIV) ~= 1 and player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneIV) <= os.time() then + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.LavaPumpWarzoneIV) ~= 1 and player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneIV) <= os.time() then player:teleportTo(Position(fromPosition.x, fromPosition.y + 1, fromPosition.z)) - player:sendTextMessage( - MESSAGE_EVENT_ADVANCE, - "You cannot enter this warzone. \z - The enemy still pumps lava into this area. Find a way to stop the pumps!" - ) - elseif player:getStorageValue(Storage.DangerousDepths.Access.TimerWarzoneIV) > os.time() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot enter this warzone. The enemy still pumps lava into this area. Find a way to stop the pumps!") + elseif player:getStorageValue(Storage.Quest.U11_50.DangerousDepths.Access.TimerWarzoneIV) > os.time() then player:teleportTo(warzoneIV) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Entering the warzone.") end end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + return true end diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_lever.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_lever.lua index 161aaafb3e7..bd4e2b171fe 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_lever.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_lever.lua @@ -1,104 +1,69 @@ local config = { boss = { - name = "Ferumbras Mortal Shell", + name = "Ascending Ferumbras", position = Position(33392, 31473, 14), }, + timeToFightAgain = 60 * 60 * 20 * 24, playerPositions = { - { pos = Position(33269, 31477, 14), teleport = Position(33390, 31483, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(33270, 31477, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33269, 31477, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33269, 31478, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33269, 31479, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33269, 31480, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33269, 31481, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33270, 31478, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33270, 31479, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33270, 31480, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33270, 31481, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33271, 31477, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33271, 31478, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33271, 31479, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33271, 31480, 14), teleport = Position(33392, 31479, 14) }, + { pos = Position(33271, 31481, 14), teleport = Position(33392, 31479, 14) }, }, specPos = { - from = Position(33374, 31458, 14), - to = Position(33414, 31498, 14), + from = Position(33379, 31460, 14), + to = Position(33405, 31485, 14), }, exit = Position(33319, 32318, 13), - centerRoom = Position(33392, 31473, 14), - summonName = "Rift Fragment", - maxSummon = 3, -} - -local leverFerumbras = Action() - -function leverFerumbras.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") - return true - end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position, true, true) - for b = 1, config.maxSummon do - local xrand = math.random(-5, 5) - local yrand = math.random(-5, 5) - local position = Position(config.boss.position.x + xrand, config.boss.position.y + yrand, config.boss.position.z) - Game.createMonster(config.summonName, position) - end - - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + monsters = { + { name = "rift invader", pos = Position(33385, 31466, 14) }, + { name = "rift invader", pos = Position(33396, 31466, 14) }, + { name = "rift invader", pos = Position(33392, 31480, 14) }, + { name = "rift invader", pos = Position(33392, 31468, 14) }, + { name = "rift invader", pos = Position(33385, 31473, 14) }, + { name = "rift invader", pos = Position(33398, 31478, 14) }, + { name = "rift invader", pos = Position(33384, 31478, 14) }, + { name = "rift invader", pos = Position(33390, 31463, 14) }, + { name = "rift invader", pos = Position(33400, 31473, 14) }, + { name = "rift invader", pos = Position(33400, 31465, 14) }, + }, + onUseExtra = function(player) + local crystals = { + [1] = { crystalPosition = Position(33390, 31468, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal1 }, + [2] = { crystalPosition = Position(33394, 31468, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal2 }, + [3] = { crystalPosition = Position(33397, 31471, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal3 }, + [4] = { crystalPosition = Position(33397, 31475, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal4 }, + [5] = { crystalPosition = Position(33394, 31478, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal5 }, + [6] = { crystalPosition = Position(33390, 31478, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal6 }, + [7] = { crystalPosition = Position(33387, 31475, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal7 }, + [8] = { crystalPosition = Position(33387, 31471, 14), globalStorage = Storage.Quest.U10_90.FerumbrasAscension.Crystals.Crystal8 }, + } + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.Crystals.AllCrystals, 0) + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.FerumbrasEssence, 0) + for _, crystal in pairs(crystals) do + local tile = Tile(crystal.crystalPosition) + if tile then + local item = tile:getItemById(14961) + if item then + item:transform(14955) end end + Game.setStorageValue(crystal.globalStorage, 0) end - end - return monstersRemoved -end + end, +} -leverFerumbras:uid(1021) +local leverFerumbras = BossLever(config) +leverFerumbras:position(Position(33270, 31476, 14)) leverFerumbras:register() diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_mazoran.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_mazoran.lua index 56cda9fb65b..aa564b94fd6 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_mazoran.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_mazoran.lua @@ -1,104 +1,56 @@ local config = { - boss = { - name = "Mazoran", - position = Position(33584, 32689, 14), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds + centerRoom = Position(33584, 32689, 14), + BossPosition = Position(33584, 32689, 14), playerPositions = { - { pos = Position(33593, 32644, 14), teleport = Position(33585, 32693, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33593, 32645, 14), teleport = Position(33585, 32693, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33593, 32646, 14), teleport = Position(33585, 32693, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33593, 32647, 14), teleport = Position(33585, 32693, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33593, 32648, 14), teleport = Position(33585, 32693, 14), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33570, 32677, 14), - to = Position(33597, 32700, 14), + Position(33593, 32644, 14), + Position(33593, 32645, 14), + Position(33593, 32646, 14), + Position(33593, 32647, 14), + Position(33593, 32648, 14), }, - exit = Position(33319, 32318, 13), + newPosition = Position(33585, 32693, 14), } local leverMazoran = Action() function leverMazoran.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if player:getPosition() ~= Position(33593, 32644, 14) then + item:transform(8912) return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) end - local boss = Game.createMonster(config.boss.name, config.boss.position) - if boss then - boss:setReward(true) - end - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + local playersTable = {} + if player:doCheckBossRoom("Mazoran", Position(33572, 32679, 14), Position(33599, 32701, 14)) then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Mazoran.") + return true + end + end + Game.createMonster("Mazoran", config.BossPosition, true, true) + for y = 32644, 32648 do + local playerTile = Tile(Position(33593, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.MazoranTimer, os.time() + os.time() + 60 * 60 * 2 * 24) + table.insert(playersTable, playerTile:getId()) end end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33572, 32679, 14), Position(33599, 32701, 14), Position(33319, 32318, 13)) + item:transform(8912) end + elseif item.itemid == 8912 then + item:transform(8911) end - return monstersRemoved + + return true end leverMazoran:uid(1025) diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_plagirath.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_plagirath.lua index b49a0d58db8..82d5535f8e6 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_plagirath.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_plagirath.lua @@ -1,102 +1,57 @@ local config = { - boss = { - name = "Plagirath", - position = Position(33172, 31501, 13), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds + centerRoom = Position(33172, 31501, 13), + BossPosition = Position(33172, 31501, 13), playerPositions = { - { pos = Position(33229, 31500, 13), teleport = Position(33173, 31504, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33229, 31501, 13), teleport = Position(33173, 31504, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33229, 31502, 13), teleport = Position(33173, 31504, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33229, 31503, 13), teleport = Position(33173, 31504, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33229, 31504, 13), teleport = Position(33173, 31504, 13), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33159, 31488, 13), - to = Position(33190, 31515, 13), + Position(33229, 31500, 13), + Position(33229, 31501, 13), + Position(33229, 31502, 13), + Position(33229, 31503, 13), + Position(33229, 31504, 13), }, - exit = Position(33319, 32318, 13), + newPosition = Position(33173, 31504, 13), } local leverPlagirath = Action() function leverPlagirath.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) + if item.itemid == 8911 then + if player:getPosition() ~= Position(33229, 31500, 13) then + item:transform(8912) return true end end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.PlagirathTimer) >= 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait a while, recently someone challenge Plagirath.") return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position) - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - - if item.itemid == 8911 then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Plagirath.") + return true + end + end + Game.createMonster("Plagirath", config.BossPosition, true, true) + for y = 31500, 31504 do + local playerTile = Tile(Position(33229, y, 13)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.PlagirathTimer, os.time() + 60 * 60 * 24 * 2) + end + end + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.PlagirathTimer, 1) + addEvent(clearForgotten, 30 * 60 * 1000, Position(33159, 31491, 13), Position(33185, 31513, 13), Position(33319, 32318, 13), Storage.Quest.U10_90.FerumbrasAscension.PlagirathTimer) item:transform(8912) - else + elseif item.itemid == 8912 then item:transform(8911) end return true end -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end - end - end - end - end - return monstersRemoved -end - leverPlagirath:uid(1022) leverPlagirath:register() diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ragiaz.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ragiaz.lua index cbe9d13ba35..e63df82d82d 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ragiaz.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ragiaz.lua @@ -1,113 +1,58 @@ local config = { - boss = { - name = "Ragiaz", - position = Position(33481, 32334, 13), + centerRoom = Position(33481, 32334, 13), + BossPosition = Position(33481, 32334, 13), + newPosition = Position(33482, 32339, 13), + deathDragons = { + Position(33476, 32331, 13), + Position(33476, 32340, 13), + Position(33487, 32340, 13), + Position(33488, 32331, 13), }, - - timeToDefeat = 17 * 60, -- 17 minutes in seconds - playerPositions = { - { pos = Position(33456, 32356, 13), teleport = Position(33482, 32339, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33457, 32356, 13), teleport = Position(33482, 32339, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33458, 32356, 13), teleport = Position(33482, 32339, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33459, 32356, 13), teleport = Position(33482, 32339, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33460, 32356, 13), teleport = Position(33482, 32339, 13), effect = CONST_ME_TELEPORT }, - }, - monsters = { - { name = "Death Dragon", pos = Position(33476, 32331, 13) }, - { name = "Death Dragon", pos = Position(33476, 32340, 13) }, - { name = "Death Dragon", pos = Position(33487, 32340, 13) }, - { name = "Death Dragon", pos = Position(33488, 32331, 13) }, - }, - specPos = { - from = Position(33468, 32319, 13), - to = Position(33495, 32347, 13), - }, - exit = Position(33319, 32318, 13), } local leverRagiaz = Action() function leverRagiaz.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if player:getPosition() ~= Position(33456, 32356, 13) then + item:transform(8912) return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) end - Game.createMonster(config.boss.name, config.boss.position) - - for i = 1, #config.monsters do - local monsterConfig = config.monsters[i] - Game.createMonster(monsterConfig.name, monsterConfig.pos, true, true) - end - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + local playersTable = {} + if player:doCheckBossRoom("Ragiaz", Position(33472, 32323, 13), Position(33493, 32347, 13)) then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Ragiaz.") + return true + end + end + Game.createMonster("Ragiaz", config.BossPosition, true, true) + for d = 1, #config.deathDragons do + Game.createMonster("Death Dragon", config.deathDragons[d], true, true) + end + for x = 33456, 33460 do + local playerTile = Tile(Position(x, 32356, 13)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.RagiazTimer, os.time() + 60 * 60 * 2 * 24) + table.insert(playersTable, playerTile:getId()) end end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33472, 32323, 13), Position(33493, 32347, 13), Position(33319, 32318, 13)) + item:transform(8912) end + elseif item.itemid == 8912 then + item:transform(8911) end - return monstersRemoved + + return true end leverRagiaz:uid(1023) diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_rat_lever.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_rat_lever.lua index 13ef7bb84e2..97cb6fef4f9 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_rat_lever.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_rat_lever.lua @@ -1,15 +1,15 @@ local config = { boss = { - name = "The Lord of The Lice", + name = "The Lord of the Lice", position = Position(33220, 31460, 12), }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds + timeToFightAgain = 2 * 24 * 60 * 60, playerPositions = { - { pos = Position(33197, 31475, 11), teleport = Position(33215, 31470, 12), effect = CONST_ME_TELEPORT }, - { pos = Position(33198, 31475, 11), teleport = Position(33215, 31470, 12), effect = CONST_ME_TELEPORT }, - { pos = Position(33199, 31475, 11), teleport = Position(33215, 31470, 12), effect = CONST_ME_TELEPORT }, - { pos = Position(33200, 31475, 11), teleport = Position(33215, 31470, 12), effect = CONST_ME_TELEPORT }, - { pos = Position(33201, 31475, 11), teleport = Position(33215, 31470, 12), effect = CONST_ME_TELEPORT }, + { pos = Position(33201, 31475, 11), teleport = Position(33215, 31470, 12) }, + { pos = Position(33197, 31475, 11), teleport = Position(33215, 31470, 12) }, + { pos = Position(33198, 31475, 11), teleport = Position(33215, 31470, 12) }, + { pos = Position(33199, 31475, 11), teleport = Position(33215, 31470, 12) }, + { pos = Position(33200, 31475, 11), teleport = Position(33215, 31470, 12) }, }, specPos = { from = Position(33187, 31429, 12), @@ -18,85 +18,6 @@ local config = { exit = Position(33319, 32318, 13), } -local ferumbrasAscendantRatLever = Action() - -function ferumbrasAscendantRatLever.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") - return true - end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position) - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local bossRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() and creature:getName() == bossName then - creature:remove() - bossRemoved = true - end - end - end - end - end - return bossRemoved -end - -ferumbrasAscendantRatLever:uid(1030) -ferumbrasAscendantRatLever:register() +local leverLordOfTheLice = BossLever(config) +leverLordOfTheLice:position(Position(33202, 31475, 11)) +leverLordOfTheLice:register() diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_razzagorn.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_razzagorn.lua index c24ec5d2e37..fe5b4e06ed9 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_razzagorn.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_razzagorn.lua @@ -1,102 +1,50 @@ local config = { - boss = { - name = "Razzagorn", - position = Position(33422, 32467, 14), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds - playerPositions = { - { pos = Position(33386, 32455, 14), teleport = Position(33419, 32467, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33387, 32455, 14), teleport = Position(33419, 32467, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33388, 32455, 14), teleport = Position(33419, 32467, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33389, 32455, 14), teleport = Position(33419, 32467, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33390, 32455, 14), teleport = Position(33419, 32467, 14), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33407, 32453, 14), - to = Position(33439, 32481, 14), - }, - exit = Position(33319, 32318, 13), + centerRoom = Position(33422, 32467, 14), + BossPosition = Position(33422, 32467, 14), + newPosition = Position(33419, 32467, 14), } local leverRazzagorn = Action() function leverRazzagorn.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) + if item.itemid == 8911 then + if player:getPosition() ~= Position(33386, 32455, 14) then + item:transform(8912) return true end end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.RazzagornTimer) >= 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait a while, recently someone challenge Razzagorn.") return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position) - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - - if item.itemid == 8911 then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Razzagorn.") + return true + end + end + Game.createMonster("Razzagorn", config.BossPosition, true, true) + for x = 33386, 33390 do + local playerTile = Tile(Position(x, 32455, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.RazzagornTimer, os.time() + 60 * 60 * 2 * 24) + end + end + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.RazzagornTimer, 1) + addEvent(clearForgotten, 30 * 60 * 1000, Position(33408, 32454, 14), Position(33440, 32480, 14), Position(33319, 32318, 13), Storage.Quest.U10_90.FerumbrasAscension.RazzagornTimer) item:transform(8912) - else + elseif item.itemid == 8912 then item:transform(8911) end return true end -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end - end - end - end - end - return monstersRemoved -end - leverRazzagorn:uid(1024) leverRazzagorn:register() diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_shulgrax.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_shulgrax.lua index 43f5029a6ac..2b1792a9261 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_shulgrax.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_shulgrax.lua @@ -1,101 +1,55 @@ local config = { - boss = { - name = "Shulgrax", - position = Position(33485, 32786, 13), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds + centerRoom = Position(33485, 32786, 13), + BossPosition = Position(33485, 32786, 13), playerPositions = { - { pos = Position(33434, 32785, 13), teleport = Position(33485, 32790, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33434, 32786, 13), teleport = Position(33485, 32790, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33434, 32787, 13), teleport = Position(33485, 32790, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33434, 32788, 13), teleport = Position(33485, 32790, 13), effect = CONST_ME_TELEPORT }, - { pos = Position(33434, 32789, 13), teleport = Position(33485, 32790, 13), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33474, 32775, 13), - to = Position(33496, 32798, 13), + Position(33434, 32785, 13), + Position(33434, 32786, 13), + Position(33434, 32787, 13), + Position(33434, 32788, 13), + Position(33434, 32789, 13), }, - exit = Position(33319, 32318, 13), + newPosition = Position(33485, 32790, 13), } local leverShulgrax = Action() function leverShulgrax.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if player:getPosition() ~= Position(33434, 32785, 13) then + item:transform(8912) return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) end - - Game.createMonster(config.boss.name, config.boss.position) - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + local playersTable = {} + if player:doCheckBossRoom("Shulgrax", Position(33473, 32776, 13), Position(33496, 32798, 13)) then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Shulgrax.") + return true + end + end + Game.createMonster("Shulgrax", config.BossPosition, true, true) + for y = 32785, 32789 do + local playerTile = Tile(Position(33434, y, 13)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.ShulgraxTimer, os.time() + 60 * 60 * 2 * 24) + table.insert(playersTable, playerTile:getId()) end end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33473, 32776, 13), Position(33496, 32798, 13), Position(33319, 32318, 13)) + item:transform(8912) end + elseif item.itemid == 8912 then + item:transform(8911) end - return monstersRemoved + + return true end leverShulgrax:uid(1028) diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_tarbaz.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_tarbaz.lua index dfda8c76e8d..7423b8f3820 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_tarbaz.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_tarbaz.lua @@ -1,101 +1,48 @@ local config = { - boss = { - name = "Tarbaz", - position = Position(33459, 32844, 11), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds - playerPositions = { - { pos = Position(33418, 32849, 11), teleport = Position(33459, 32848, 11), effect = CONST_ME_TELEPORT }, - { pos = Position(33418, 32850, 11), teleport = Position(33459, 32848, 11), effect = CONST_ME_TELEPORT }, - { pos = Position(33418, 32851, 11), teleport = Position(33459, 32848, 11), effect = CONST_ME_TELEPORT }, - { pos = Position(33418, 32852, 11), teleport = Position(33459, 32848, 11), effect = CONST_ME_TELEPORT }, - { pos = Position(33418, 32853, 11), teleport = Position(33459, 32848, 11), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33447, 32832, 11), - to = Position(33473, 32856, 11), - }, - exit = Position(33319, 32318, 13), + centerRoom = Position(33459, 32844, 11), + BossPosition = Position(33459, 32844, 11), + newPosition = Position(33459, 32848, 11), } local leverTarbaz = Action() function leverTarbaz.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if player:getPosition() ~= Position(33418, 32849, 11) then + item:transform(8912) return true end - table.insert(players, creature) end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position) - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + local playersTable = {} + if player:doCheckBossRoom("Tarbaz", Position(33446, 32833, 11), Position(33515, 32875, 12)) then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Tarbaz.") + return true + end + end + Game.createMonster("Tarbaz", config.BossPosition, true, true) + for y = 32849, 32853 do + local playerTile = Tile(Position(33418, y, 11)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TarbazTimer, os.time() + 60 * 60 * 2 * 24) + table.insert(playersTable, playerTile:getId()) end end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33446, 32833, 11), Position(33515, 32875, 12), Position(33319, 32318, 13)) + item:transform(8912) end + elseif item.itemid == 8912 then + item:transform(8911) end - return monstersRemoved + + return true end leverTarbaz:uid(1027) diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_lever.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_lever.lua index 221a4bdc850..6782d30c024 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_lever.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_lever.lua @@ -3,110 +3,21 @@ local config = { name = "The Shatterer", position = Position(33406, 32418, 14), }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds + timeToFightAgain = 2 * 24 * 60 * 60, playerPositions = { - { pos = Position(33403, 32465, 13), teleport = Position(33398, 32414, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33404, 32465, 13), teleport = Position(33398, 32414, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33405, 32465, 13), teleport = Position(33398, 32414, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33406, 32465, 13), teleport = Position(33398, 32414, 14), effect = CONST_ME_TELEPORT }, - { pos = Position(33407, 32465, 13), teleport = Position(33398, 32414, 14), effect = CONST_ME_TELEPORT }, + { pos = Position(33403, 32465, 13), teleport = Position(33398, 32414, 14) }, + { pos = Position(33404, 32465, 13), teleport = Position(33398, 32414, 14) }, + { pos = Position(33405, 32465, 13), teleport = Position(33398, 32414, 14) }, + { pos = Position(33406, 32465, 13), teleport = Position(33398, 32414, 14) }, + { pos = Position(33407, 32465, 13), teleport = Position(33398, 32414, 14) }, }, specPos = { from = Position(33377, 32390, 14), to = Position(33446, 32447, 14), }, exit = Position(33319, 32318, 13), - centerRoom = Position(33406, 32418, 14), - storage = { - lever = Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, - timer = Storage.Quest.U10_90.FerumbrasAscension.TheShattererTimer, - }, } -local ferumbrasAscendantTheShattererLever = Action() - -function ferumbrasAscendantTheShattererLever.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.centerRoom, false, false, 30, 30, 30, 30) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with The Shatterer.") - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") - return true - end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) - end - - Game.createMonster(config.boss.name, config.boss.position, true, true) - - for _, participant in pairs(players) do - participant:setStorageValue(config.storage.lever, 0) - participant:setStorageValue(config.storage.timer, 1) - end - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit, config.storage.timer) - - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local bossRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() and creature:getName() == bossName then - creature:remove() - bossRemoved = true - end - end - end - end - end - return bossRemoved -end - -ferumbrasAscendantTheShattererLever:uid(1029) -ferumbrasAscendantTheShattererLever:register() +local leverShatterer = BossLever(config) +leverShatterer:position(Position(33402, 32465, 13)) +leverShatterer:register() diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_levers.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_levers.lua index b7e7916ebdf..3189947919b 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_levers.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_the_shatterer_levers.lua @@ -39,11 +39,13 @@ local chains = { } local ferumbrasAscendantTheShattererLevers = Action() + function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, target, toPosition, isHotkey) if player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShatterer) >= 1 then player:sendCancelMessage("You cannot use this lever again.") return true end + if item.itemid == 8911 then item:transform(8912) if item:getPosition() == Position(33385, 32410, 14) then @@ -55,10 +57,10 @@ function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, Game.createMonster("Fury", { x = player:getPosition().x + math.random(-3, 3), y = player:getPosition().y + math.random(-3, 3), z = player:getPosition().z }) end end - player:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, math.max(player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever), 0) + 1) - if player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) + 1) + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then local boss = Tile(Position(33406, 32418, 14)):getTopCreature() - if boss and boss:getName():lower() == "the shatterer" then + if boss:getName():lower() == "the shatterer" then boss:teleportTo(Position(33400, 32415, 14)) boss:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true @@ -73,10 +75,10 @@ function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, Game.createMonster("Destroyer", { x = player:getPosition().x + math.random(-3, 3), y = player:getPosition().y + math.random(-3, 3), z = player:getPosition().z }) end end - player:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, math.max(player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever), 0) + 1) - if player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) + 1) + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then local boss = Tile(Position(33406, 32418, 14)):getTopCreature() - if boss and boss:getName():lower() == "the shatterer" then + if boss:getName():lower() == "the shatterer" then boss:teleportTo(Position(33400, 32415, 14)) boss:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true @@ -90,10 +92,10 @@ function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, bla:remove() end end - player:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, math.max(player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever), 0) + 1) - if player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) + 1) + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then local boss = Tile(Position(33406, 32418, 14)):getTopCreature() - if boss and boss:getName():lower() == "the shatterer" then + if boss:getName():lower() == "the shatterer" then boss:teleportTo(Position(33400, 32415, 14)) boss:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true @@ -107,10 +109,10 @@ function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, bla:remove() end end - player:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, math.max(player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever), 0) + 1) - if player:getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then + Game.setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever, Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) + 1) + if Game.getStorageValue(Storage.Quest.U10_90.FerumbrasAscension.TheShattererLever) >= 4 then local boss = Tile(Position(33406, 32418, 14)):getTopCreature() - if boss and boss:getName():lower() == "the shatterer" then + if boss:getName():lower() == "the shatterer" then boss:teleportTo(Position(33400, 32415, 14)) boss:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true @@ -122,6 +124,7 @@ function ferumbrasAscendantTheShattererLevers.onUse(player, item, fromPosition, player:sendCancelMessage("Sorry, not possible.") return true end + return true end diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_zamulosh.lua b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_zamulosh.lua index 74e7740bc9f..fc3e34a8219 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_zamulosh.lua +++ b/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_zamulosh.lua @@ -1,18 +1,8 @@ local config = { - boss = { - name = "Zamulosh", - position = Position(33643, 32756, 11), - }, - timeToDefeat = 17 * 60, -- 17 minutes in seconds - playerPositions = { - { pos = Position(33680, 32741, 11), teleport = Position(33644, 32760, 11), effect = CONST_ME_TELEPORT }, - }, - specPos = { - from = Position(33632, 32747, 11), - to = Position(33654, 32765, 11), - }, - exit = Position(33319, 32318, 13), - summons = { + centerRoom = Position(33643, 32756, 11), + BossPosition = Position(33643, 32756, 11), + newPosition = Position(33644, 32760, 11), + zamuloshSummons = { Position(33642, 32756, 11), Position(33642, 32756, 11), Position(33642, 32756, 11), @@ -25,91 +15,45 @@ local config = { local leverZamulosh = Action() function leverZamulosh.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local spectators = Game.getSpectators(config.specPos.from, false, false, 0, 0, 0, 0, config.specPos.to) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - player:say("Someone is already inside the room.", TALKTYPE_MONSTER_SAY) - return true - end - end - - if isBossInRoom(config.specPos.from, config.specPos.to, config.boss.name) then - player:say("The room is being cleared. Please wait a moment.", TALKTYPE_MONSTER_SAY) - return true - end - - local players = {} - for i = 1, #config.playerPositions do - local pos = config.playerPositions[i].pos - local creature = Tile(pos):getTopCreature() - if not creature or not creature:isPlayer() then - player:sendCancelMessage("You need " .. #config.playerPositions .. " players to challenge " .. config.boss.name .. ".") + if item.itemid == 8911 then + if player:getPosition() ~= Position(33680, 32741, 11) then + item:transform(8912) return true end - table.insert(players, creature) - end - - for i = 1, #players do - local playerToTeleport = players[i] - local teleportPos = config.playerPositions[i].teleport - local effect = config.playerPositions[i].effect - playerToTeleport:teleportTo(teleportPos) - teleportPos:sendMagicEffect(effect) end - - Game.createMonster(config.boss.name, config.boss.position) - - local zamuloshIndex = math.random(#config.summons) - - for i, summonPos in ipairs(config.summons) do - if i == zamuloshIndex then - Game.createMonster(config.boss.name, summonPos) - else - Game.createMonster("Zamulosh3", summonPos) - end - end - - addEvent(clearBossRoom, config.timeToDefeat * 1000, config.specPos.from, config.specPos.to, config.exit) - if item.itemid == 8911 then - item:transform(8912) - else - item:transform(8911) - end - - return true -end - -function clearBossRoom(fromPos, toPos, exitPos) - local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) - for _, spec in pairs(spectators) do - if spec:isPlayer() then - spec:teleportTo(exitPos) - exitPos:sendMagicEffect(CONST_ME_TELEPORT) - spec:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") - else - spec:remove() - end - end -end - -function isBossInRoom(fromPos, toPos, bossName) - local monstersRemoved = false - for x = fromPos.x, toPos.x do - for y = fromPos.y, toPos.y do - for z = fromPos.z, toPos.z do - local tile = Tile(Position(x, y, z)) - if tile then - local creature = tile:getTopCreature() - if creature and creature:isMonster() then - creature:remove() - monstersRemoved = true - end + local playersTable = {} + if player:doCheckBossRoom("Zamulosh", Position(33634, 32749, 11), Position(33654, 32765, 11)) then + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Zamulosh.") + return true + end + end + Game.createMonster("Zamulosh", config.BossPosition, true, true) + for d = 1, #config.zamuloshSummons do + Game.createMonster("Zamulosh3", config.zamuloshSummons[d], true, true) + end + for y = 32741, 32745 do + local playerTile = Tile(Position(33680, y, 11)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U10_90.FerumbrasAscension.ZamuloshTimer, os.time() + 60 * 60 * 2 * 24) + table.insert(playersTable, playerTile:getId()) end end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33634, 32749, 11), Position(33654, 32765, 11), Position(33319, 32318, 13)) + item:transform(8912) end + elseif item.itemid == 8912 then + item:transform(8911) end - return monstersRemoved + + return true end leverZamulosh:uid(1026) diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_bird_cage.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_bird_cage.lua index 36206829675..53d507e6b73 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_bird_cage.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_bird_cage.lua @@ -15,10 +15,10 @@ function forgottenKnowledgeBird.onUse(player, item, fromPosition, target, toPosi end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You open the cage and let the cave parrot roam free!") item:transform(23812) - if player:getStorageValue(Storage.ForgottenKnowledge.BirdCounter) < 0 then - player:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, 0) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter) < 0 then + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter, 0) end - player:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, player:getStorageValue(Storage.ForgottenKnowledge.BirdCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter, player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter) + 1) end player:getPosition():sendMagicEffect(CONST_ME_HEARTS) return true diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_dragonking_zyrtarch.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_dragonking_zyrtarch.lua new file mode 100644 index 00000000000..426177864b2 --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_dragonking_zyrtarch.lua @@ -0,0 +1,52 @@ +local config = { + bossPosition = Position(33357, 31182, 10), + newPosition = Position(33359, 31186, 10), + soulPosition = Position(33359, 31182, 12), +} + +local monsters = { + { position = Position(33352, 31187, 10) }, + { position = Position(33363, 31187, 10) }, + { position = Position(33353, 31176, 10) }, + { position = Position(33363, 31176, 10) }, +} + +local leverZyrtarch = Action() + +function leverZyrtarch.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(33391, 31178, 10) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom("Dragonking Zyrtarch", Position(33348, 31172, 10), Position(33368, 31190, 12)) then + for d = 1, #monsters do + Game.createMonster("soulcatcher", monsters[d].position, true, true) + end + Game.createMonster("dragonking zyrtarch", config.bossPosition, true, true) + Game.createMonster("soul of dragonking zyrtarch", config.soulPosition, true, true) + for y = 31178, 31182 do + local playerTile = Tile(Position(33391, y, 10)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.DragonkingTimer, os.time() + 20 * 60 * 60) + table.insert(playersTable, playerTile:getId()) + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(33348, 31172, 10), Position(33368, 31190, 12), Position(33407, 31172, 10)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + + return true +end + +leverZyrtarch:position(Position(33391, 31177, 10)) +leverZyrtarch:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_fount.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_fount.lua index 09501839c9e..1b7b0a4a3e9 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_fount.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_fount.lua @@ -1,11 +1,11 @@ local forgottenKnowledgeFount = Action() function forgottenKnowledgeFount.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.ForgottenKnowledge.Phial) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Phial) >= 1 then return false end player:addItem(23810) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "A phial of fresh pond water. It looks crystal clear and sparkles a little.") - player:setStorageValue(Storage.ForgottenKnowledge.Phial, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Phial, 1) return true end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_frozen_horror.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_frozen_horror.lua new file mode 100644 index 00000000000..fc7e5049b6a --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_frozen_horror.lua @@ -0,0 +1,59 @@ +local config = { + centerRoom = Position(32269, 31091, 14), + BossPosition = Position(32269, 31091, 14), + newPosition = Position(32271, 31097, 14), +} + +local monsters = { + { monster = "icicle", pos = Position(32266, 31084, 14) }, + { monster = "icicle", pos = Position(32272, 31084, 14) }, + { monster = "dragon egg", pos = Position(32269, 31084, 14) }, + { monster = "melting frozen horror", pos = Position(32267, 31071, 14) }, +} + +local leverMeltingFrozenHorror = Action() + +function leverMeltingFrozenHorror.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(32302, 31088, 14) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.HorrorTimer) >= 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait a while, recently someone challenge Frozen Horror.") + return true + end + local specs, spec = Game.getSpectators(config.centerRoom, false, false, 15, 15, 15, 15) + for i = 1, #specs do + spec = specs[i] + if spec:isPlayer() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Someone is fighting with Frozen Horror.") + return true + end + end + for n = 1, #monsters do + Game.createMonster(monsters[n].monster, monsters[n].pos, true, true) + end + Game.createMonster("solid frozen horror", config.BossPosition, true, true) + for y = 31088, 31092 do + local playerTile = Tile(Position(32302, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.HorrorTimer, os.stime() + 20 * 60 * 60) + end + end + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.HorrorTimer, 1) + addEvent(clearForgotten, 30 * 60 * 1000, Position(32264, 31070, 14), Position(32284, 31104, 14), Position(32319, 31091, 14), Storage.Quest.U11_02.ForgottenKnowledge.HorrorTimer) + item:transform(8912) + elseif item.itemid == 8912 then + item:transform(8911) + end + return true +end + +leverMeltingFrozenHorror:position(Position(32302, 31087, 14)) +leverMeltingFrozenHorror:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_girl_picture.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_girl_picture.lua index b065f3e3de2..c7995ab4a94 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_girl_picture.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_girl_picture.lua @@ -1,9 +1,9 @@ local forgottenKnowledgeGirl = Action() function forgottenKnowledgeGirl.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.ForgottenKnowledge.GirlPicture) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.GirlPicture) >= 1 then return false end - player:setStorageValue(Storage.ForgottenKnowledge.GirlPicture, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.GirlPicture, 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Seems that an old silver key appears in the drower.") item:remove() return true diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lady_tenebris.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lady_tenebris.lua new file mode 100644 index 00000000000..7f784c4516f --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lady_tenebris.lua @@ -0,0 +1,43 @@ +local config = { + centerRoom = Position(32912, 31599, 14), + bossPosition = Position(32912, 31599, 14), + newPosition = Position(32911, 31603, 14), +} + +local leverLadyTenebris = Action() + +function leverLadyTenebris.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(32902, 31623, 14) then + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom("Lady Tenebris", Position(32902, 31589, 14), Position(32924, 31610, 14)) then + for d = 1, 6 do + Game.createMonster("shadow tentacle", Position(math.random(32909, 32914), math.random(31596, 31601), 14), true, true) + end + Game.createMonster("lady tenebris", config.bossPosition, true, true) + for y = 31623, 31627 do + local playerTile = Tile(Position(32902, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LadyTenebrisTimer, os.time() + 20 * 60 * 60) + table.insert(playersTable, playerTile:getId()) + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(32902, 31589, 14), Position(32924, 31610, 14), Position(32919, 31639, 14)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + + return true +end + +leverLadyTenebris:position(Position(32902, 31622, 14)) +leverLadyTenebris:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lloyd.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lloyd.lua new file mode 100644 index 00000000000..2a6a48b84c6 --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_lloyd.lua @@ -0,0 +1,51 @@ +local config = { + centerRoom = Position(32799, 32832, 14), + bossPosition = Position(32799, 32827, 14), + newPosition = Position(32800, 32831, 14), +} + +local monsters = { + { cosmic = "cosmic energy prism a", pos = Position(32801, 32827, 14) }, + { cosmic = "cosmic energy prism b", pos = Position(32798, 32827, 14) }, + { cosmic = "cosmic energy prism c", pos = Position(32803, 32826, 14) }, + { cosmic = "cosmic energy prism d", pos = Position(32796, 32826, 14) }, +} + +local leverLloyd = Action() + +function leverLloyd.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(32759, 32868, 14) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom(player:getId(), "Lloyd", Position(32785, 32814, 14), Position(32812, 32838, 14)) then + for n = 1, #monsters do + Game.createMonster(monsters[n].cosmic, monsters[n].pos, true, true) + end + Game.createMonster("lloyd", config.bossPosition, true, true) + for y = 32868, 32872 do + local playerTile = Tile(Position(32759, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LloydTimer, os.time() + 20 * 60 * 60) + table.insert(playersTable, playerTile:getId()) + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(32785, 32814, 14), Position(32812, 32838, 14), Position(32815, 32873, 13)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + + return true +end + +leverLloyd:position(Position(32759, 32867, 14)) +leverLloyd:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_old_desk.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_old_desk.lua index 3bbc0175e5d..a33e1aa4cfd 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_old_desk.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_old_desk.lua @@ -1,22 +1,22 @@ local forgottenKnowledgeOldDesk = Action() function forgottenKnowledgeOldDesk.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.ForgottenKnowledge.SilverKey) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.SilverKey) >= 1 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already get an old silver key.") return true end - if player:getStorageValue(Storage.ForgottenKnowledge.GirlPicture) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.GirlPicture) >= 1 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You find an old silver key inside of the drower.") player:addItem(23733, true, true) - player:setStorageValue(Storage.ForgottenKnowledge.SilverKey, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.SilverKey, 1) return true end - if player:getStorageValue(Storage.ForgottenKnowledge.OldDesk) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.OldDesk) >= 1 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already get an old note.") return true end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "As you open the drower a ghostly apparition shortly appears hovering over the desk. You find an old note inside of the drower.") player:addItem(23731, true, true) - player:setStorageValue(Storage.ForgottenKnowledge.OldDesk, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.OldDesk, 1) return true end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_plant.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_plant.lua index d0306018ce5..65715560a67 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_plant.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_plant.lua @@ -403,7 +403,7 @@ local function revertTree() tree:getPosition():sendMagicEffect(CONST_ME_POFF) tree:transform(6189) end - Game.setStorageValue(GlobalStorage.ForgottenKnowledge.ActiveTree, 0) + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.ActiveTree, 0) for v = 1, #dry do Game.createItem(dry[v].itemid, 1, dry[v].position) local pos = Position(dry[v].position) @@ -429,16 +429,16 @@ function forgottenKnowledgePlant.onUse(player, item, fromPosition, target, toPos target:getPosition():sendMagicEffect(CONST_ME_SMALLPLANTS) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The birch grows as you pour the sparkling water from the phial over it.") addEvent(revertItem, 10 * 60 * 1000, target:getPosition(), 26483, 26482) - if player:getStorageValue(Storage.ForgottenKnowledge.PlantCounter) < 0 then - player:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, 0) + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter) < 0 then + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter, 0) end - player:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, player:getStorageValue(Storage.ForgottenKnowledge.PlantCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter, player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter) + 1) elseif target.itemid == 6180 and target:getPosition() == Position(32737, 32116, 10) then - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.ActiveTree) >= 1 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.ActiveTree) >= 1 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot use the phial while the trees still have life and colour.") return true end - if player:getStorageValue(Storage.ForgottenKnowledge.PlantCounter) < 5 or player:getStorageValue(Storage.ForgottenKnowledge.BirdCounter) < 3 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter) < 5 or player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter) < 3 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Seems that you don't make grow enough trees or not free the parrots.") return true end @@ -477,7 +477,7 @@ function forgottenKnowledgePlant.onUse(player, item, fromPosition, target, toPos end end end - Game.setStorageValue(GlobalStorage.ForgottenKnowledge.ActiveTree, 1) + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.ActiveTree, 1) addEvent(revertTree, 1 * 60 * 1000) Game.createItem(11108, 1, Position(32736, 32117, 10)) local teleport = Game.createItem(775, 1, Position(32736, 32117, 10)) diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_secret_wall.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_secret_wall.lua index 674e9fd5b42..0d9e3a3acff 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_secret_wall.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_secret_wall.lua @@ -7,7 +7,7 @@ function forgottenKnowledgeSecret.onUse(player, item, fromPosition, target, toPo if not player:getItemById(23738, true) then return false end - if player:getStorageValue(Storage.ForgottenKnowledge.SilverKey) < 1 or not player:getItemById(23733, true) then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.SilverKey) < 1 or not player:getItemById(23733, true) then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have the fitting key.") return true end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_servants_mechanism.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_servants_mechanism.lua index eb2d9588662..8c2ca9f5bf1 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_servants_mechanism.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_servants_mechanism.lua @@ -1,19 +1,19 @@ local config = { - [26663] = { storage = GlobalStorage.ForgottenKnowledge.MechanismDiamond, counter = GlobalStorage.ForgottenKnowledge.DiamondServant, msg = "5 diamond entities are consuming too much raw energy for the cosmic chamber to awaken, it will be put to rest again in 10 minutes." }, - [26664] = { storage = GlobalStorage.ForgottenKnowledge.MechanismGolden, counter = GlobalStorage.ForgottenKnowledge.GoldenServant, msg = "5 golden entities are consuming too much raw energy for the cosmic chamber to awaken, it will be put to rest again in 10 minutes." }, + [26663] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.MechanismDiamond, counter = Storage.Quest.U11_02.ForgottenKnowledge.DiamondServant, msg = "5 diamond entities are consuming too much raw energy for the cosmic chamber to awaken, it will be put to rest again in 10 minutes." }, + [26664] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.MechanismGolden, counter = Storage.Quest.U11_02.ForgottenKnowledge.GoldenServant, msg = "5 golden entities are consuming too much raw energy for the cosmic chamber to awaken, it will be put to rest again in 10 minutes." }, } local function clearGolems() local specs, spec = Game.getSpectators(Position(32815, 32874, 13), false, false, 63, 63, 63, 63) for i = 1, #specs do spec = specs[i] - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismDiamond) < 1 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismDiamond) < 1 then if spec:isMonster() and spec:getName():lower() == "diamond servant replica" then spec:getPosition():sendMagicEffect(CONST_ME_POFF) spec:remove() end end - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismGolden) < 1 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.MechanismGolden) < 1 then if spec:isMonster() and spec:getName():lower() == "golden servant replica" then spec:getPosition():sendMagicEffect(CONST_ME_POFF) spec:remove() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_last_lore_keeper.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_last_lore_keeper.lua new file mode 100644 index 00000000000..aa704ba6435 --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_last_lore_keeper.lua @@ -0,0 +1,51 @@ +local config = { + { newPosition = Position(31985, 32851, 14) }, + { pos = Position(31986, 32840, 14), monster = "a shielded astral glyph" }, + { pos = Position(31975, 32856, 15), monster = "bound astral power" }, + { pos = Position(31987, 32839, 14), monster = "the astral source" }, + { pos = Position(31986, 32823, 15), monster = "the distorted astral source" }, + { pos = Position(31989, 32823, 15), monster = "an astral glyph" }, +} + +local leverLoreKeeper = Action() + +function leverLoreKeeper.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(32019, 32844, 14) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom("The Last Lorekeeper", Position(31968, 32821, 14), Position(32004, 32865, 15)) then + for x = 32018, 32020 do + for y = 32844, 32848 do + local playerTile = Tile(Position(x, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config[1].newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LastLoreTimer, os.time() + 60 * 60 * 14 * 24) + table.insert(playersTable, playerTile:getId()) + end + end + end + for b = 2, #config do + Game.createMonster(config[b].monster, config[b].pos, true, true) + end + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralPowerCounter, 1) + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph, 0) + player:say("The Astral Glyph begins to draw upon bound astral power to expel you from the room!", TALKTYPE_MONSTER_SAY) + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(31968, 32821, 14), Position(32004, 32865, 15), Position(32035, 32859, 14)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + + return true +end + +leverLoreKeeper:position(Position(32019, 32843, 14)) +leverLoreKeeper:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_thorn_knight.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_thorn_knight.lua new file mode 100644 index 00000000000..16b22300ea1 --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_thorn_knight.lua @@ -0,0 +1,43 @@ +local config = { + centerRoom = Position(32624, 32880, 14), + bossPosition = Position(32624, 32880, 14), + newPosition = Position(32624, 32886, 14), +} + +local leverThornKnight = Action() + +function leverThornKnight.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(32657, 32877, 14) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom("Thorn Knight", Position(32613, 32869, 14), Position(32636, 32892, 14)) then + for d = 1, 6 do + Game.createMonster("possessed tree", Position(math.random(32619, 32629), math.random(32877, 32884), 14), true, true) + end + Game.createMonster("mounted thorn knight", config.bossPosition, true, true) + for y = 32877, 32881 do + local playerTile = Tile(Position(32657, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.ThornKnightTimer, os.stime() + 20 * 60 * 60) + table.insert(playersTable, playerTile:getId()) + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(32613, 32869, 14), Position(32636, 32892, 14), Position(32678, 32888, 14)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + return true +end + +leverThornKnight:position(Position(32657, 32876, 14)) +leverThornKnight:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_time_guardian.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_time_guardian.lua new file mode 100644 index 00000000000..75dcd0da028 --- /dev/null +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_the_time_guardian.lua @@ -0,0 +1,47 @@ +local config = { + centerRoom = Position(32977, 31662, 14), + newPosition = Position(32977, 31667, 14), +} + +local bosses = { + { bossPosition = Position(32977, 31662, 14), bossName = "The Time Guardian" }, + { bossPosition = Position(32975, 31664, 13), bossName = "The Freezing Time Guardian" }, + { bossPosition = Position(32980, 31664, 13), bossName = "The Blazing Time Guardian" }, +} + +local leverTimeGuardian = Action() + +function leverTimeGuardian.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 8911 then + if player:getPosition() ~= Position(33010, 31660, 14) then + item:transform(8912) + return true + end + end + if item.itemid == 8911 then + local playersTable = {} + if player:doCheckBossRoom("The Time Guardian", Position(32967, 31654, 13), Position(32989, 31677, 14)) then + for q = 1, #bosses do + Game.createMonster(bosses[q].bossName, bosses[q].bossPosition, true, true) + end + for y = 31660, 31664 do + local playerTile = Tile(Position(33010, y, 14)):getTopCreature() + if playerTile and playerTile:isPlayer() then + playerTile:getPosition():sendMagicEffect(CONST_ME_POFF) + playerTile:teleportTo(config.newPosition) + playerTile:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + playerTile:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianTimer, os.time() + 20 * 60 * 60) + table.insert(playersTable, playerTile:getId()) + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, Position(32967, 31654, 13), Position(32989, 31677, 14), Position(32870, 32724, 14)) + item:transform(8912) + end + elseif item.itemid == 8912 then + item:transform(8911) + end + return true +end + +leverTimeGuardian:position(Position(33010, 31659, 14)) +leverTimeGuardian:register() diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_time_machine.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_time_machine.lua index bc92b403adf..52188508827 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_time_machine.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/actions_time_machine.lua @@ -1,4 +1,5 @@ local timeMachine = Action() + function timeMachine.onUse(player, item, fromPosition, target, toPosition, isHotkey) if player:getPosition() == Position(32870, 32723, 15) then player:teleportTo(Position(32870, 32724, 14)) diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_astral_source.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_astral_source.lua index 9d243f4be65..d7d0d869513 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_astral_source.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_astral_source.lua @@ -2,7 +2,7 @@ local astralSource = CreatureEvent("AstralSource") function astralSource.onThink(creature) local hp = (creature:getHealth() / creature:getMaxHealth()) * 100 local health, difference, glyph, pos = 0, 0, Tile(Position(31989, 32823, 15)):getTopCreature(), creature:getPosition() - if hp < 5.5 and Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph) >= 1 then + if hp < 5.5 and Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph) >= 1 then sourcePos = creature:getPosition() creature:say("Your damage distorted the source and prevents the Glyph to draw on its power.", TALKTYPE_MONSTER_SAY) creature:remove() @@ -23,7 +23,7 @@ function astralSource.onThink(creature) glyph:say("Without the power of the source the Glyph loses its protection!", TALKTYPE_MONSTER_SAY) end end - elseif Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph) < 1 then + elseif Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph) < 1 then creature:addHealth(10000, false) end end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bosses_kill.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bosses_kill.lua index 6bd27821be6..00ced55f16d 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bosses_kill.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bosses_kill.lua @@ -1,19 +1,20 @@ local bosses = { -- bosses - ["lady tenebris"] = { storage = Storage.ForgottenKnowledge.LadyTenebrisKilled }, - ["the enraged thorn knight"] = { storage = Storage.ForgottenKnowledge.ThornKnightKilled }, - ["lloyd"] = { storage = Storage.ForgottenKnowledge.LloydKilled }, - ["soul of dragonking zyrtarch"] = { storage = Storage.ForgottenKnowledge.DragonkingKilled }, - ["melting frozen horror"] = { storage = Storage.ForgottenKnowledge.HorrorKilled }, - ["the time guardian"] = { storage = Storage.ForgottenKnowledge.TimeGuardianKilled }, - ["the blazing time guardian"] = { storage = Storage.ForgottenKnowledge.TimeGuardianKilled }, - ["the freezing time guardian"] = { storage = Storage.ForgottenKnowledge.TimeGuardianKilled }, - ["the last lore keeper"] = { storage = Storage.ForgottenKnowledge.LastLoreKilled }, + ["lady tenebris"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.LadyTenebrisKilled }, + ["the enraged thorn knight"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.ThornKnightKilled }, + ["lloyd"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.LloydKilled }, + ["soul of dragonking zyrtarch"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.DragonkingKilled }, + ["melting frozen horror"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.HorrorKilled }, + ["the time guardian"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled }, + ["the blazing time guardian"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled }, + ["the freezing time guardian"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled }, + ["the last lore keeper"] = { storage = Storage.Quest.U11_02.ForgottenKnowledge.LastLoreKilled }, -- IA interactions ["an astral glyph"] = {}, } local bossesForgottenKill = CreatureEvent("ForgottenKnowledgeBossDeath") + function bossesForgottenKill.onDeath(creature) local bossConfig = bosses[creature:getName():lower()] if not bossConfig then @@ -22,10 +23,14 @@ function bossesForgottenKill.onDeath(creature) onDeathForDamagingPlayers(creature, function(creature, player) if bossConfig.storage then - player:setStorageValue(bossConfig.storage, os.time() + 20 * 3600) + if creature:getName():lower() == "the last lore keeper" then + player:setStorageValue(bossConfig.storage, os.time() + (13 * 24 * 3600) + (20 * 3600)) + else + player:setStorageValue(bossConfig.storage, os.time() + 20 * 3600) + end elseif creature:getName():lower() == "the enraged thorn knight" then - player:setStorageValue(Storage.ForgottenKnowledge.PlantCounter, 0) - player:setStorageValue(Storage.ForgottenKnowledge.BirdCounter, 0) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter, 0) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter, 0) end end) diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bound_astral_power.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bound_astral_power.lua index 3709d5c559a..be6286b7e88 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bound_astral_power.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_bound_astral_power.lua @@ -7,9 +7,9 @@ local positions = { local astralPower = CreatureEvent("BoundAstralPowerDeath") function astralPower.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) - Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter, Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter) + 1) - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter) >= 4 then - Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralPowerCounter, 1) + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralPowerCounter, Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralPowerCounter) + 1) + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralPowerCounter) >= 4 then + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralPowerCounter, 1) end local msg = "The destruction of the power source gained you more time until the glyph is powered up!" @@ -21,8 +21,8 @@ function astralPower.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller if player:getPosition():getDistance(positions[i].pos) < 7 then creature:say(msg, TALKTYPE_MONSTER_SAY, false, nil, positions[i].pos) Game.createMonster("bound astral power", positions[i].nextPos, true, true) - Game.setStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph, 1) - addEvent(Game.setStorageValue, 1 * 60 * 1000, GlobalStorage.ForgottenKnowledge.AstralGlyph, 0) + Game.setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph, 1) + addEvent(Game.setStorageValue, 1 * 60 * 1000, Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph, 0) end end return true diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_distorted_source.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_distorted_source.lua index 334c7bc8cf6..e8f7c799dbb 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_distorted_source.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_distorted_source.lua @@ -3,7 +3,7 @@ function distortedSource.onThink(creature) local health, difference, glyph, pos = 0, 0, Tile(Position(31989, 32823, 15)):getTopCreature(), creature:getPosition() if creature:getHealth() <= 40000 then creature:addHealth(10000, false) - elseif creature:getHealth() >= 55000 or Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph) < 1 then + elseif creature:getHealth() >= 55000 or Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph) < 1 then local spectators = Game.getSpectators(Position(31986, 32847, 14), false, false, 12, 12, 12, 12) for i = 1, #spectators do local spec = spectators[i] @@ -20,7 +20,7 @@ function distortedSource.onThink(creature) end end - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.AstralGlyph) >= 1 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AstralGlyph) >= 1 then local spectators = Game.getSpectators(Position(31986, 32847, 14), false, false, 12, 12, 12, 12) for i = 1, #spectators do local spec2 = spectators[i] diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_energy_prism_death.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_energy_prism_death.lua index 140362d92b3..5b4213feaed 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_energy_prism_death.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_energy_prism_death.lua @@ -1,6 +1,6 @@ local energyPrismDeath = CreatureEvent("EnergyPrismDeath") function energyPrismDeath.onDeath(creature) - stopEvent(Storage.ForgottenKnowledge.LloydEvent) + stopEvent(Storage.Quest.U11_02.ForgottenKnowledge.LloydEvent) local tile = Tile(Position(32799, 32826, 14)) if not tile then return false diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_lloyd_preparedeath.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_lloyd_preparedeath.lua index e00624aa53d..5804a21283c 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_lloyd_preparedeath.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_lloyd_preparedeath.lua @@ -49,7 +49,7 @@ function lloydPrepareDeath.onPrepareDeath(creature, lastHitKiller, mostDamageKil creature:getPosition():sendMagicEffect(CONST_ME_TELEPORT) creature:addHealth(300000, true) creature:say("The cosmic energies in the chamber refocus on Lloyd.", TALKTYPE_MONSTER_SAY) - Storage.ForgottenKnowledge.LloydEvent = addEvent(revertLloyd, 10 * 1000, prismCount) + Storage.Quest.U11_02.ForgottenKnowledge.LloydEvent = addEvent(revertLloyd, 10 * 1000, prismCount) end return true end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_replica_servants.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_replica_servants.lua index acb25740216..d2dbe4a1b4e 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_replica_servants.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/creaturescripts_replica_servants.lua @@ -1,11 +1,11 @@ local servants = { ["golden servant replica"] = { - storage = GlobalStorage.ForgottenKnowledge.GoldenServant, - playerStorage = Storage.ForgottenKnowledge.GoldenServantCounter, + storage = Storage.Quest.U11_02.ForgottenKnowledge.GoldenServant, + playerStorage = Storage.Quest.U11_02.ForgottenKnowledge.GoldenServantCounter, }, ["diamond servant replica"] = { - storage = GlobalStorage.ForgottenKnowledge.DiamondServant, - playerStorage = Storage.ForgottenKnowledge.DiamondServantCounter, + storage = Storage.Quest.U11_02.ForgottenKnowledge.DiamondServant, + playerStorage = Storage.Quest.U11_02.ForgottenKnowledge.DiamondServantCounter, }, } local replicaServant = CreatureEvent("ReplicaServantDeath") @@ -18,7 +18,7 @@ function replicaServant.onDeath(creature, _corpse, _lastHitKiller, mostDamageKil Game.setStorageValue(bossConfig.storage, 0) end Game.setStorageValue(bossConfig.storage, Game.getStorageValue(bossConfig.storage) + 1) - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.GoldenServant) >= 5 and Game.getStorageValue(GlobalStorage.ForgottenKnowledge.DiamondServant) >= 5 then + if Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.GoldenServant) >= 5 and Game.getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.DiamondServant) >= 5 then if not Tile(Position(32815, 32870, 13)):getItemById(10840) then local teleport = Game.createItem(10840, 1, Position(32815, 32870, 13)) if teleport then diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_challenger.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_challenger.lua index d204cd119a9..edc8ffbc61e 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_challenger.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_challenger.lua @@ -45,7 +45,7 @@ function challenger.onStepIn(creature, item, position, fromPosition) end if player:canFightBoss(teleport.boss) then if item.uid == 24882 then - if player:getStorageValue(Storage.ForgottenKnowledge.BabyDragon) < 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BabyDragon) < 1 then player:teleportTo(teleport.backPos) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You not have permission to use this teleport!") player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_entrance_teleport.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_entrance_teleport.lua index 5b327430c4b..64847b1560a 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_entrance_teleport.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_entrance_teleport.lua @@ -1,72 +1,72 @@ local destination = { [25047] = { newPos = Position(32807, 31657, 8), - storage = Storage.ForgottenKnowledge.AccessDeath, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessDeath, effect = CONST_ME_MORTAREA, }, [25048] = { newPos = Position(32325, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessDeath, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessDeath, effect = CONST_ME_MORTAREA, }, [25051] = { newPos = Position(32786, 32820, 13), - storage = Storage.ForgottenKnowledge.AccessViolet, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessViolet, effect = CONST_ME_PURPLEENERGY, }, [25052] = { newPos = Position(32328, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessViolet, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessViolet, effect = CONST_ME_PURPLEENERGY, }, [25049] = { newPos = Position(32637, 32256, 7), - storage = Storage.ForgottenKnowledge.AccessEarth, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessEarth, effect = CONST_ME_SMALLPLANTS, }, [25050] = { newPos = Position(32331, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessEarth, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessEarth, effect = CONST_ME_SMALLPLANTS, }, [25053] = { newPos = Position(33341, 31168, 7), - storage = Storage.ForgottenKnowledge.AccessFire, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessFire, effect = CONST_ME_FIREAREA, }, [25054] = { newPos = Position(32334, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessFire, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessFire, effect = CONST_ME_FIREAREA, }, [25057] = { newPos = Position(32207, 31036, 10), - storage = Storage.ForgottenKnowledge.AccessIce, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessIce, effect = CONST_ME_ICEATTACK, }, [25058] = { newPos = Position(32337, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessIce, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessIce, effect = CONST_ME_ICEATTACK, }, [25055] = { newPos = Position(32780, 32686, 14), - storage = Storage.ForgottenKnowledge.AccessGolden, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessGolden, effect = CONST_ME_YELLOWENERGY, }, [25056] = { newPos = Position(32340, 32089, 7), - storage = Storage.ForgottenKnowledge.AccessGolden, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessGolden, effect = CONST_ME_YELLOWENERGY, }, [10840] = { newPos = Position(32907, 32848, 13), - storage = Storage.ForgottenKnowledge.AccessLast, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessLast, effect = CONST_ME_ENERGYHIT, }, [10842] = { newPos = Position(32332, 32092, 7), - storage = Storage.ForgottenKnowledge.AccessLast, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessLast, effect = CONST_ME_ENERGYHIT, }, } @@ -84,16 +84,16 @@ function entranceTeleport.onStepIn(creature, item, position, fromPosition) return end if item.itemid == 10840 then - if player:getStorageValue(Storage.ForgottenKnowledge.AccessLast) < 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessLast) < 1 then if - player:getStorageValue(Storage.ForgottenKnowledge.LadyTenebrisKilled) >= 1 - and player:getStorageValue(Storage.ForgottenKnowledge.LloydKilled) >= 1 - and player:getStorageValue(Storage.ForgottenKnowledge.ThornKnightKilled) >= 1 - and player:getStorageValue(Storage.ForgottenKnowledge.DragonkingKilled) >= 1 - and player:getStorageValue(Storage.ForgottenKnowledge.HorrorKilled) >= 1 - and player:getStorageValue(Storage.ForgottenKnowledge.TimeGuardianKilled) >= 1 + player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LadyTenebrisKilled) >= 1 + and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.LloydKilled) >= 1 + and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.ThornKnightKilled) >= 1 + and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.DragonkingKilled) >= 1 + and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.HorrorKilled) >= 1 + and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.TimeGuardianKilled) >= 1 then - player:setStorageValue(Storage.ForgottenKnowledge.AccessLast, 1) + player:setStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.AccessLast, 1) end end end diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_fount.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_fount.lua index e1a11083da7..c38b3b56cc7 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_fount.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_fount.lua @@ -5,7 +5,7 @@ function fount.onStepIn(creature, item, position, fromPosition) if not player then return end - if player:getStorageValue(Storage.ForgottenKnowledge.Phial) >= 1 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.Phial) >= 1 then player:teleportTo(Position(32722, 32242, 8)) player:getPosition():sendMagicEffect(CONST_ME_WATERSPLASH) return true diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_ice_teleport.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_ice_teleport.lua index b855169c234..7854fa63f4f 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_ice_teleport.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_ice_teleport.lua @@ -1,7 +1,7 @@ local destination = { [26667] = { position = Position(32273, 31053, 13), - storage = Storage.ForgottenKnowledge.AccessMachine, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessMachine, }, } diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_lava_teleport.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_lava_teleport.lua index 1e352d3d7ea..005b6546644 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_lava_teleport.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_lava_teleport.lua @@ -1,7 +1,7 @@ local destination = { [26668] = { position = Position(33411, 31082, 10), - storage = Storage.ForgottenKnowledge.AccessLavaTeleport, + storage = Storage.Quest.U11_02.ForgottenKnowledge.AccessLavaTeleport, }, } diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_servant_teleport.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_servant_teleport.lua index 42921e1712f..bba0c98bfa8 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_servant_teleport.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_servant_teleport.lua @@ -13,7 +13,7 @@ function servantTeleport.onStepIn(creature, item, position, fromPosition) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have to wait to challenge this enemy again!") return true end - if player:getStorageValue(Storage.ForgottenKnowledge.GoldenServantCounter) >= 5 and player:getStorageValue(Storage.ForgottenKnowledge.DiamondServantCounter) >= 5 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.GoldenServantCounter) >= 5 and player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.DiamondServantCounter) >= 5 then player:teleportTo(Position(32760, 32876, 14)) player:getPosition():sendMagicEffect(CONST_ME_ENERGYHIT) return true diff --git a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_teleport_tree.lua b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_teleport_tree.lua index ea3bf54a854..d1135f65fa0 100644 --- a/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_teleport_tree.lua +++ b/data-otservbr-global/scripts/quests/forgotten_knowledge/movements_teleport_tree.lua @@ -6,7 +6,7 @@ function teleportTree.onStepIn(creature, item, position, fromPosition) return end - if player:getStorageValue(Storage.ForgottenKnowledge.PlantCounter) < 5 or player:getStorageValue(Storage.ForgottenKnowledge.BirdCounter) < 3 then + if player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.PlantCounter) < 5 or player:getStorageValue(Storage.Quest.U11_02.ForgottenKnowledge.BirdCounter) < 3 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't help in anything to enter here") player:teleportTo(Position(32737, 32117, 10)) position:sendMagicEffect(CONST_ME_TELEPORT) diff --git a/data-otservbr-global/scripts/quests/roshamuul_quest/actions_mixture.lua b/data-otservbr-global/scripts/quests/roshamuul_quest/actions_mixture.lua index 9ba1ecf88cb..cb2e30d97c8 100644 --- a/data-otservbr-global/scripts/quests/roshamuul_quest/actions_mixture.lua +++ b/data-otservbr-global/scripts/quests/roshamuul_quest/actions_mixture.lua @@ -4,6 +4,7 @@ local buckets = { } local lowerRoshamuulMixtune = Action() + function lowerRoshamuulMixtune.onUse(player, item, fromPosition, target, toPosition, isHotkey) if (target == nil) or not target:isItem() then return false diff --git a/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua b/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua index fae3fc59794..652a74af84b 100644 --- a/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua +++ b/data-otservbr-global/scripts/quests/soul_war/action-reward_soul_war.lua @@ -26,35 +26,3 @@ end rewardSoulWar:position({ x = 33620, y = 31400, z = 10 }) rewardSoulWar:register() - -local phantasmalJadeMount = Action() - -function phantasmalJadeMount.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local soulWarQuest = player:soulWarQuestKV() - if soulWarQuest:get("panthasmal-jade-mount") then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You already have Phantasmal Jade mount!") - return true - end - - if table.contains({ 34072, 34073, 34074 }, item.itemid) then - if player:getItemCount(34072) >= 4 and player:getItemCount(34073) == 1 and player:getItemCount(34074) == 1 then - player:removeItem(34072, 4) - player:removeItem(34073, 1) - player:removeItem(34074, 1) - player:addMount(167) - player:addAchievement("You got Horse Power") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won Phantasmal Jade mount.") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations! You won You got Horse Power achievement.") - player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE) - soulWarQuest:set("panthasmal-jade-mount", true) - else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have the necessary items!") - player:getPosition():sendMagicEffect(CONST_ME_POFF) - end - end - - return true -end - -phantasmalJadeMount:id(34072, 34073, 34074) -phantasmalJadeMount:register() diff --git a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua index 91273ac4cbd..e5166038db2 100644 --- a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua +++ b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua @@ -18,17 +18,25 @@ local function updateWaterPoolsSize() end local function loadMapEmpty() - if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then - local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers() - for _, player in ipairs(players) do - if player:getPosition().z == 8 then - if player:isInBoatSpot() then - local teleportPosition = player:getPosition() - teleportPosition.z = 9 - player:teleportTo(teleportPosition) - logger.trace("Teleporting player to down.") + local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers() + local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters() + if playersInZone > 0 or monstersInZone > 0 then + local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures() + for _, creature in ipairs(creatures) do + local creatureMaster = creature:getMaster() + local player = creature:getPlayer() + if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then + if creature:getPosition().z == 8 then + if creature:isInBoatSpot() then + local teleportPosition = creature:getPosition() + teleportPosition.z = 9 + creature:teleportTo(teleportPosition) + logger.trace("Teleporting player to down.") + end + if player then + player:sendCreatureAppear() + end end - player:sendCreatureAppear() end end end @@ -72,22 +80,30 @@ local function findNearestRoomPosition(playerPosition) end local function loadMapInundate() - if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then - local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers() - for _, player in ipairs(players) do - local playerPosition = player:getPosition() - if playerPosition.z == 9 then - if player:isInBoatSpot() then - local nearestCenterPosition = findNearestRoomPosition(playerPosition) - player:teleportTo(nearestCenterPosition) - logger.trace("Teleporting player to the near center position room and updating tile.") - else - player:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition) - logger.trace("Teleporting player to wait position and updating tile.") + local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers() + local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters() + if playersInZone > 0 or monstersInZone > 0 then + local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures() + for _, creature in ipairs(creatures) do + local creatureMaster = creature:getMaster() + local player = creature:getPlayer() + if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then + local creaturePosition = creature:getPosition() + if creaturePosition.z == 9 then + if creature:isInBoatSpot() then + local nearestCenterPosition = findNearestRoomPosition(creaturePosition) + creature:teleportTo(nearestCenterPosition) + logger.trace("Teleporting player to the near center position room and updating tile.") + else + creature:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition) + logger.trace("Teleporting player to wait position and updating tile.") + end + creaturePosition:sendMagicEffect(CONST_ME_TELEPORT) + end + if player then + player:sendCreatureAppear() end - playerPosition:sendMagicEffect(CONST_ME_TELEPORT) end - player:sendCreatureAppear() end end diff --git a/data-otservbr-global/scripts/quests/the_djinn_war_quest/action_water_fountain.lua b/data-otservbr-global/scripts/quests/the_djinn_war_quest/action_water_fountain.lua index 0f8ae9f8ac5..9586aae2d80 100644 --- a/data-otservbr-global/scripts/quests/the_djinn_war_quest/action_water_fountain.lua +++ b/data-otservbr-global/scripts/quests/the_djinn_war_quest/action_water_fountain.lua @@ -11,5 +11,5 @@ function action_water_fountain.onUse(player, item, fromPosition, target, toPosit return true end -action_water_fountain:aid(5390) +action_water_fountain:aid(12105) action_water_fountain:register() diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/actions_lair_entrance.lua b/data-otservbr-global/scripts/quests/the_first_dragon/actions_lair_entrance.lua index 2c03f4d86e3..c2666382616 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/actions_lair_entrance.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/actions_lair_entrance.lua @@ -1,7 +1,7 @@ local lairEntrance = Action() function lairEntrance.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.FirstDragon.AccessCave) <= 3 then + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave) <= 3 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not worthy to enter in The First Dragon's Lair yet.") return true end diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/actions_lever.lua b/data-otservbr-global/scripts/quests/the_first_dragon/actions_lever.lua index 2e794aa7fa8..ff4c20ff88d 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/actions_lever.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/actions_lever.lua @@ -1,127 +1,50 @@ -local lever = Action() - local config = { - centerRoom = { x = 33616, y = 31022, z = 14 }, - range = 10, - storage = Storage.FirstDragon.FirstDragonTimer, - monsterPosition = { - { position = Position(33574, 31013, 14) }, - { position = Position(33592, 31013, 14) }, - { position = Position(33583, 31022, 14) }, - { position = Position(33574, 31031, 14) }, - { position = Position(33592, 31031, 14) }, + boss = { + name = "spirit of fertility", + position = Position(33625, 31021, 14), }, + timeToFightAgain = 20 * 60 * 60, playerPositions = { - Position(33582, 30993, 14), - Position(33583, 30993, 14), - Position(33584, 30993, 14), - Position(33582, 30994, 14), - Position(33583, 30994, 14), - Position(33584, 30994, 14), - Position(33582, 30995, 14), - Position(33583, 30995, 14), - Position(33584, 30995, 14), - Position(33582, 30996, 14), - Position(33583, 30996, 14), - Position(33584, 30996, 14), - Position(33582, 30997, 14), - Position(33583, 30997, 14), - Position(33584, 30997, 14), - }, - toPosition1 = Position(33574, 31017, 14), - roomTile1 = { - { fromPosition = Position(33582, 30993, 14) }, - { fromPosition = Position(33583, 30993, 14) }, - { fromPosition = Position(33584, 30993, 14) }, - }, - toPosition2 = Position(33592, 31017, 14), - roomTile2 = { - { fromPosition = Position(33582, 30994, 14) }, - { fromPosition = Position(33583, 30994, 14) }, - { fromPosition = Position(33584, 30994, 14) }, + { pos = Position(33583, 30993, 14), teleport = Position(33592, 31017, 14) }, + { pos = Position(33582, 30993, 14), teleport = Position(33574, 31017, 14) }, + { pos = Position(33584, 30993, 14), teleport = Position(33592, 31035, 14) }, + { pos = Position(33582, 30994, 14), teleport = Position(33574, 31035, 14) }, + { pos = Position(33583, 30994, 14), teleport = Position(33583, 31026, 14) }, + { pos = Position(33584, 30994, 14), teleport = Position(33574, 31017, 14) }, + { pos = Position(33582, 30995, 14), teleport = Position(33592, 31017, 14) }, + { pos = Position(33583, 30995, 14), teleport = Position(33592, 31035, 14) }, + { pos = Position(33584, 30995, 14), teleport = Position(33574, 31035, 14) }, + { pos = Position(33582, 30996, 14), teleport = Position(33583, 31026, 14) }, + { pos = Position(33583, 30996, 14), teleport = Position(33574, 31017, 14) }, + { pos = Position(33584, 30996, 14), teleport = Position(33592, 31017, 14) }, + { pos = Position(33582, 30997, 14), teleport = Position(33592, 31035, 14) }, + { pos = Position(33583, 30997, 14), teleport = Position(33574, 31035, 14) }, + { pos = Position(33584, 30997, 14), teleport = Position(33583, 31026, 14) }, }, - toPosition3 = Position(33592, 31035, 14), - roomTile3 = { - { fromPosition = Position(33582, 30995, 14) }, - { fromPosition = Position(33583, 30995, 14) }, - { fromPosition = Position(33584, 30995, 14) }, + specPos = { + from = Position(33566, 31006, 14), + to = Position(33626, 31032, 14), }, - toPosition4 = Position(33574, 31035, 14), - roomTile4 = { - { fromPosition = Position(33582, 30996, 14) }, - { fromPosition = Position(33583, 30996, 14) }, - { fromPosition = Position(33584, 30996, 14) }, + monsters = { + { name = "fallen challenger", pos = Position(33592, 31013, 14) }, + { name = "fallen challenger", pos = Position(33583, 31022, 14) }, + { name = "fallen challenger", pos = Position(33574, 31013, 14) }, + { name = "fallen challenger", pos = Position(33574, 31031, 14) }, + { name = "fallen challenger", pos = Position(33592, 31031, 14) }, + { name = "unbeatable dragon", pos = Position(math.random(33610, 33622), math.random(31016, 31030), 14) }, + { name = "unbeatable dragon", pos = Position(math.random(33610, 33622), math.random(31016, 31030), 14) }, + { name = "unbeatable dragon", pos = Position(math.random(33610, 33622), math.random(31016, 31030), 14) }, + { name = "unbeatable dragon", pos = Position(math.random(33610, 33622), math.random(31016, 31030), 14) }, + { name = "unbeatable dragon", pos = Position(math.random(33610, 33622), math.random(31016, 31030), 14) }, }, - toPosition5 = Position(33583, 31026, 14), - roomTile5 = { - { fromPosition = Position(33582, 30997, 14) }, - { fromPosition = Position(33583, 30997, 14) }, - { fromPosition = Position(33584, 30997, 14) }, - }, -} - -function lever.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item.itemid == 8911 then - for i = 1, #config.playerPositions do - local creature = Tile(config.playerPositions[i]):getTopCreature() - if not creature then - item:transform(8912) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need 5 players to fight with this boss.") - return true - end + exit = Position(33597, 30994, 14), + onUseExtra = function(creature) + if creature and creature:isPlayer() then + creature:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable, 0) end - end - if item.itemid == 8911 then - if roomIsOccupied(config.centerRoom, false, config.range, config.range) then - player:say("Someone is fighting against the boss! You need wait awhile.", TALKTYPE_MONSTER_SAY) - return true - end - - for d = 1, 5 do - Game.createMonster("unbeatable dragon", Position(math.random(33610, 33622), math.random(31016, 31030), 14), true, true) - end - for b = 1, #config.monsterPosition do - Game.createMonster("fallen challenger", config.monsterPosition[b].position, true, true) - end - for i = 1, #config.playerPositions do - local creature = Tile(config.playerPositions[i]):getTopCreature() - if creature then - for i = 1, #config.roomTile1 do - local toRoom1 = Tile(config.roomTile1[i].fromPosition):getTopCreature() - if toRoom1 then - toRoom1:teleportTo(config.toPosition1) - end - local toRoom2 = Tile(config.roomTile2[i].fromPosition):getTopCreature() - if toRoom2 then - toRoom2:teleportTo(config.toPosition2) - end - local toRoom3 = Tile(config.roomTile3[i].fromPosition):getTopCreature() - if toRoom3 then - toRoom3:teleportTo(config.toPosition3) - end - local toRoom4 = Tile(config.roomTile4[i].fromPosition):getTopCreature() - if toRoom4 then - toRoom4:teleportTo(config.toPosition4) - end - local toRoom5 = Tile(config.roomTile5[i].fromPosition):getTopCreature() - if toRoom5 then - toRoom5:teleportTo(config.toPosition5) - end - end - creature:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - creature:setStorageValue(config.storage, os.time() + 20 * 3600) - creature:setStorageValue(Storage.FirstDragon.SomewhatBeatable, 0) - end - end - -- One hour for clean the room - addEvent(clearRoom, 60 * 60 * 1000, Position(33583, 31022, 14), 50, 50, config.storage) - Game.createMonster("spirit of fertility", Position(33625, 31021, 14), true, true) - item:transform(8912) - elseif item.itemid == 8912 then - item:transform(8911) - end - return true -end + end, +} -lever:uid(30003) -lever:register() +local leverFirstDragon = BossLever(config) +leverFirstDragon:position(Position(33583, 30992, 14)) +leverFirstDragon:register() diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/actions_rewards.lua b/data-otservbr-global/scripts/quests/the_first_dragon/actions_rewards.lua index 2d1c8ac2a90..bbef9b99c1b 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/actions_rewards.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/actions_rewards.lua @@ -6,13 +6,13 @@ local bpItems = { { name = "gold token", count = 3 }, { name = "blue gem", count = 1 }, { name = "yellow gem", count = 1 }, - { id = 3039, count = 1 }, -- red gem + { name = "red gem", count = 1 }, { name = "demon horn", count = 2 }, { name = "slime heart", count = 2 }, { name = "energy vein", count = 2 }, { name = "petrified scream", count = 2 }, { name = "brimstone shell", count = 2 }, - { name = "deepling wart", count = 2 }, + { name = "deepling warts", count = 2 }, { name = "wyrm scale", count = 2 }, { name = "hellspawn tail", count = 2 }, } @@ -33,36 +33,44 @@ local chests = { } local finalReward = Action() + function finalReward.onUse(player, item, fromPosition, target, toPosition, isHotkey) local setting = chests[item.uid] if not setting then return true end - if item.uid == 14021 and player:getStorageValue(Storage.FirstDragon.RewardFeather) < os.time() then + + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) ~= 2 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are not eligible to claim these rewards yet.") + return true + end + + if item.uid == 14021 and player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardMask) < os.time() then player:addItem(setting.name, setting.count, true) - player:setStorageValue(Storage.FirstDragon.RewardFeather, os.time() + 24 * 3600) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardMask, os.time() + 60 * 60 * 24 * 5) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You found " .. setting.count .. " " .. setting.name .. ".") - elseif item.uid == 14022 and player:getStorageValue(Storage.FirstDragon.RewardBackpack) < os.time() then + elseif item.uid == 14022 and player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardBackpack) < os.time() then local bp = Game.createItem("Backpack", 1) if bp then for i = 1, #bpItems do if bpItems[i].id then - bp:addItem(bpItems[i].id, count) + bp:addItem(bpItems[i].id, bpItems[i].count) else - bp:addItem(bpItems[i].name, count) + bp:addItem(bpItems[i].name, bpItems[i].count) end end bp:moveTo(player) end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You found a backpack.") - player:setStorageValue(Storage.FirstDragon.RewardBackpack, os.time() + 60 * 60 * 365 * 24) - elseif item.uid == 14023 and player:getStorageValue(Storage.FirstDragon.RewardMask) < os.time() then + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardBackpack, os.time() + 60 * 60 * 24 * 365) + elseif item.uid == 14023 and player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardFeather) < os.time() then player:addItem(setting.name, setting.count, true) - player:setStorageValue(Storage.FirstDragon.RewardMask, os.time() + 60 * 60 * 5 * 24) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.RewardFeather, os.time() + 24 * 3600) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You found " .. setting.count .. " " .. setting.name .. ".") else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The " .. getItemName(setting.itemId) .. " is empty.") + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.") end + return true end diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/actions_sacrifice_items.lua b/data-otservbr-global/scripts/quests/the_first_dragon/actions_sacrifice_items.lua index 19144117c54..0a9cd03ccaf 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/actions_sacrifice_items.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/actions_sacrifice_items.lua @@ -1,8 +1,8 @@ local config = { - [24939] = { storage = Storage.FirstDragon.Scale }, - [24940] = { storage = Storage.FirstDragon.Tooth }, - [24941] = { storage = Storage.FirstDragon.Horn }, - [24942] = { storage = Storage.FirstDragon.Bones }, + [24939] = { storage = Storage.Quest.U11_02.TheFirstDragon.Scale }, + [24940] = { storage = Storage.Quest.U11_02.TheFirstDragon.Tooth }, + [24941] = { storage = Storage.Quest.U11_02.TheFirstDragon.Horn }, + [24942] = { storage = Storage.Quest.U11_02.TheFirstDragon.Bones }, } local sacrificeItems = Action() @@ -18,20 +18,20 @@ function sacrificeItems.onUse(player, item, fromPosition, target, toPosition, is return true end - if player:getStorageValue(Storage.FirstDragon.AccessCave) >= 4 then + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave) >= 4 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You're plunging " .. item:getName() .. " into the lava. You are now worthy to enter The First Dragon's Lair. Touch the lava pool again.") return true end - if player:getStorageValue(Storage.FirstDragon.AccessCave) < 0 then - player:setStorageValue(Storage.FirstDragon.AccessCave, 0) + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave) < 0 then + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave, 0) end local targetPosition = Position(33047, 32712, 3) if toPosition == targetPosition then local targetId = Tile(targetPosition):getItemById(25160) if targetId then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You're plunging " .. item:getName() .. " into the lava.") - player:setStorageValue(Storage.FirstDragon.AccessCave, player:getStorageValue(Storage.FirstDragon.AccessCave) + 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave, player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.AccessCave) + 1) player:setStorageValue(setting.storage, 1) item:remove(1) return true diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/actions_treasure_chest.lua b/data-otservbr-global/scripts/quests/the_first_dragon/actions_treasure_chest.lua index d40aec690d2..edbcba3184f 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/actions_treasure_chest.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/actions_treasure_chest.lua @@ -84,26 +84,30 @@ local UniqueTable = { } local treasureChest = Action() + function treasureChest.onUse(player, item, fromPosition, target, toPosition, isHotkey) local setting = UniqueTable[item.uid] if not setting then return false end - if player:getStorageValue(item.uid) >= 1 then - player:sendTextMessage(string.format(MESSAGE_EVENT_ADVANCE, "The %s is empty.", item:getName())) + local storageValue = player:getStorageValue(item.uid) + if storageValue > 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The " .. item:getName() .. " is empty.") return true end - if player:getStorageValue(Storage.FirstDragon.ChestCounter) >= 19 then + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter) >= 19 then player:addAchievement("Treasure Hunter") player:addItem(setting.name or setting.itemId, setting.count, true) player:setStorageValue(item.uid, 1) - player:setStorageValue(Storage.FirstDragon.ChestCounter, player:getStorageValue(Storage.FirstDragon.ChestCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter, player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter) + 1) return true end + player:setStorageValue(item.uid, 1) - player:setStorageValue(Storage.FirstDragon.ChestCounter, player:getStorageValue(Storage.FirstDragon.ChestCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter, player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.ChestCounter) + 1) + if setting.name then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You found " .. setting.count .. " " .. setting.name .. ".") player:addItem(setting.name, setting.count, true) diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_first_dragon.lua b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_first_dragon.lua index 90a2451066c..c347f907e09 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_first_dragon.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_first_dragon.lua @@ -25,7 +25,9 @@ function deathFirstDragon.onDeath(creature, corpse, lasthitkiller, mostdamagekil if spec:isPlayer() then spec:teleportTo(Position(33617, 31020, 13)) spec:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - spec:setStorageValue(Storage.FirstDragon.Feathers, 1) + if spec:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers) < 1 then + spec:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.Feathers, 1) + end end end return true diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_somewhat_beatable.lua b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_somewhat_beatable.lua index be0cab0cd7b..13308f03d97 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_somewhat_beatable.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_death_somewhat_beatable.lua @@ -6,15 +6,15 @@ function deathSomewhatBeatable.onDeath(creature, target) local spec = spectators[i] if spec:isPlayer() then if creature:getName():lower() == "somewhat beatable" then - if spec:getStorageValue(Storage.FirstDragon.SomewhatBeatable) < 5 then - spec:setStorageValue(Storage.FirstDragon.SomewhatBeatable, spec:getStorageValue(Storage.FirstDragon.SomewhatBeatable) + 1) + if spec:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable) < 5 then + spec:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable, spec:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable) + 1) end end - if spec:getStorageValue(Storage.FirstDragon.SomewhatBeatable) == 5 then + if spec:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable) == 5 then for b = 1, 6 do Game.createMonster("dragon essence", Position(math.random(33609, 33624), math.random(31017, 31028), 14), true, true) end - spec:setStorageValue(Storage.FirstDragon.SomewhatBeatable, 0) + spec:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.SomewhatBeatable, 0) end end end diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_kill_dragon.lua b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_kill_dragon.lua index 55045c65e9d..af6bef08e29 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_kill_dragon.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/creaturescripts_kill_dragon.lua @@ -2,9 +2,9 @@ local killDragon = CreatureEvent("TheFirstDragonDragonTaskDeath") function killDragon.onDeath(creature, _corpse, _lastHitKiller, mostDamageKiller) onDeathForParty(creature, mostDamageKiller, function(creature, player) - local storage = player:getStorageValue(Storage.FirstDragon.DragonCounter) + local storage = player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.DragonCounter) if storage >= 0 and storage < 200 then - player:setStorageValue(Storage.FirstDragon.DragonCounter, player:getStorageValue(Storage.FirstDragon.DragonCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.DragonCounter, player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.DragonCounter) + 1) end end) return true diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/movements_entrance_teleport.lua b/data-otservbr-global/scripts/quests/the_first_dragon/movements_entrance_teleport.lua index 9eb046b74f7..8543eff38c5 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/movements_entrance_teleport.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/movements_entrance_teleport.lua @@ -1,7 +1,7 @@ local UniqueTable = { -- Tazhadur entrance [35001] = { - storage = Storage.FirstDragon.DragonCounter, + storage = Storage.Quest.U11_02.TheFirstDragon.DragonCounter, value = 200, range = 10, newPos = { x = 32015, y = 32466, z = 8 }, @@ -10,8 +10,8 @@ local UniqueTable = { }, -- Kalyassa entrance [35002] = { - storage = Storage.FirstDragon.ChestCounter, - value = 5, + storage = Storage.Quest.U11_02.TheFirstDragon.ChestCounter, + value = 4, range = 10, newPos = { x = 32078, y = 32456, z = 8 }, bossName = "Kalyassa", @@ -19,7 +19,7 @@ local UniqueTable = { }, -- Zorvorax entrance [35003] = { - storage = Storage.FirstDragon.SecretsCounter, + storage = Storage.Quest.U11_02.TheFirstDragon.SecretsCounter, value = 3, range = 10, newPos = { x = 32008, y = 32396, z = 8 }, @@ -28,7 +28,7 @@ local UniqueTable = { }, -- Gelidrazah entrance [35004] = { - storage = Storage.FirstDragon.GelidrazahAccess, + storage = Storage.Quest.U11_02.TheFirstDragon.GelidrazahAccess, value = 1, range = 10, newPos = { x = 32076, y = 32402, z = 8 }, @@ -65,7 +65,7 @@ function entranceTeleport.onStepIn(creature, item, position, fromPosition) return true end - if player:getStorageValue(Storage.FirstDragon.Questline) < 1 or player:getStorageValue(setting.storage) < setting.value then + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.Questline) < 1 or player:getStorageValue(setting.storage) < setting.value then player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) player:teleportTo(fromPosition) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/movements_last_teleport.lua b/data-otservbr-global/scripts/quests/the_first_dragon/movements_last_teleport.lua index 310fabe8cd7..80509399d64 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/movements_last_teleport.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/movements_last_teleport.lua @@ -1,27 +1,43 @@ local lastTeleport = MoveEvent() +local function isDateWithinEvent() + local currentDate = os.date("*t") + local startDate = { day = 14, month = 1 } + local endDate = { day = 12, month = 2 } + + if (currentDate.month == startDate.month and currentDate.day >= startDate.day) or (currentDate.month == endDate.month and currentDate.day <= endDate.day) or (currentDate.month > startDate.month and currentDate.month < endDate.month) then + return true + end + return false +end + function lastTeleport.onStepIn(creature, item, position, fromPosition) local player = creature:getPlayer() if not player then return end - local setting = UniqueTable[item.uid] - if not setting then + local destination = { x = 33585, y = 30990, z = 14 } + + if not isDateWithinEvent() then + player:teleportTo(fromPosition, true) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This teleport is only available between January 14 and February 12.") + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true end - if player:getStorageValue(Storage.FirstDragon.FirstDragonTimer) < os.time() then + if player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.FirstDragonTimer) < os.time() then position:sendMagicEffect(CONST_ME_TELEPORT) - player:teleportTo(setting.destination) + player:teleportTo(destination) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) else player:teleportTo(fromPosition, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have to wait to challenge The First Dragon again!") player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end + return true end -lastTeleport:uid(24894) +lastTeleport:uid(24889) lastTeleport:register() diff --git a/data-otservbr-global/scripts/quests/the_first_dragon/movements_zorvorax_secrets.lua b/data-otservbr-global/scripts/quests/the_first_dragon/movements_zorvorax_secrets.lua index 16ea14e9fcd..36772967418 100644 --- a/data-otservbr-global/scripts/quests/the_first_dragon/movements_zorvorax_secrets.lua +++ b/data-otservbr-global/scripts/quests/the_first_dragon/movements_zorvorax_secrets.lua @@ -1,18 +1,15 @@ local UniqueTable = { [25002] = { - storage = Storage.FirstDragon.DesertTile, - msg = "You enter the beautiful oasis. \ - By visiting this sacred site you're infused with the power of water bringing life to the desert.", + storage = Storage.Quest.U11_02.TheFirstDragon.DesertTile, + msg = "You enter the beautiful oasis. By visiting this sacred site you're infused with the power of water bringing life to the desert.", }, [25003] = { - storage = Storage.FirstDragon.StoneSculptureTile, - msg = "You enter the circle of trees and flowers. \ - By visiting this sacred site you're infused with the power of nature and plants.", + storage = Storage.Quest.U11_02.TheFirstDragon.StoneSculptureTile, + msg = "You enter the circle of trees and flowers. By visiting this sacred site you're infused with the power of nature and plants.", }, [25004] = { - storage = Storage.FirstDragon.SuntowerTile, - msg = "You entered the suntower of Ab'dendriel. \ - By visiting this sacred site you're infused with the power of the life-giving sun.", + storage = Storage.Quest.U11_02.TheFirstDragon.SuntowerTile, + msg = "You entered the suntower of Ab'dendriel. By visiting this sacred site you're infused with the power of the life-giving sun.", }, } @@ -31,7 +28,7 @@ function zorvoraxSecrets.onStepIn(creature, item, position, fromPosition) if player:getStorageValue(setting.storage) < 1 then player:setStorageValue(setting.storage, 1) - player:setStorageValue(Storage.FirstDragon.SecretsCounter, player:getStorageValue(Storage.FirstDragon.SecretsCounter) + 1) + player:setStorageValue(Storage.Quest.U11_02.TheFirstDragon.SecretsCounter, player:getStorageValue(Storage.Quest.U11_02.TheFirstDragon.SecretsCounter) + 1) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, setting.msg) return true end diff --git a/data-otservbr-global/scripts/quests/the_hidden_city_of_beregar/actions_ladder.lua b/data-otservbr-global/scripts/quests/the_hidden_city_of_beregar/actions_ladder.lua index 5260bc4469a..83074b595e3 100644 --- a/data-otservbr-global/scripts/quests/the_hidden_city_of_beregar/actions_ladder.lua +++ b/data-otservbr-global/scripts/quests/the_hidden_city_of_beregar/actions_ladder.lua @@ -1,7 +1,7 @@ local dwarvenLadder = Action() function dwarvenLadder.onUse(player, item, fromPosition, itemEx, toPosition) if player:getStorageValue(Storage.DwarvenLegs) < 1 then - player:teleportTo({ x = 32681, y = 31507, z = 10 }) + player:teleportTo({ x = 32681, y = 31507, z = 10 }, true) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) return true else diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_asura_mirror.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_asura_mirror.lua deleted file mode 100644 index 0659f5f95e0..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_asura_mirror.lua +++ /dev/null @@ -1,21 +0,0 @@ -local goPos = { x = 32813, y = 32754, z = 9 } - -local asuraMirror = Action() -function asuraMirror.onUse(creature, item, position, fromPosition, pos, target, toPosition) - local player = creature:getPlayer() - if not player then - return - end - - if player:getLevel() >= 250 then - position:sendMagicEffect(CONST_ME_TELEPORT) - player:teleportTo(goPos) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - else - player:sendCancelMessage("You do not have enough level.") - end - return true -end - -asuraMirror:aid(64019) -asuraMirror:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_basinfire.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_basinfire.lua deleted file mode 100644 index b37eede46ca..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_basinfire.lua +++ /dev/null @@ -1,18 +0,0 @@ -local basinFire = Action() - -function basinFire.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 8 then - if target.itemid == 2114 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a reward.") - player:setStorageValue(Storage.TheSecretLibrary.Mota, 9) - player:removeItem(32408, 1) - player:addItem(32623, 1) - player:setStorageValue(Storage.TheSecretLibrary.BasinDoor, 1) - end - return true - end - return false -end - -basinFire:id(1334) -basinFire:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bastion_access.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bastion_access.lua deleted file mode 100644 index 285722c4a7a..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bastion_access.lua +++ /dev/null @@ -1,13 +0,0 @@ -local bastionAccess = Action() - -function bastionAccess.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local time = getTibiaTimerDayOrNight() - if time == "night" and target:getId() == 27836 and player:getStorageValue(Storage.TheSecretLibrary.FalconBastionAccess) == 1 then - player:teleportTo(Position({ x = 33357, y = 31308, z = 4 })) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end - return true -end - -bastionAccess:id(28468) -bastionAccess:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_blacktp.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_blacktp.lua deleted file mode 100644 index bd7e614d317..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_blacktp.lua +++ /dev/null @@ -1,14 +0,0 @@ -local backTp = Action() - -function backTp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.BlackTel) == -1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a skull.") - player:addItem(28489, 1) - player:setStorageValue(Storage.TheSecretLibrary.BlackTel, 1) - return true - end - return false -end - -backTp:uid(1098) -backTp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bluetp.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bluetp.lua deleted file mode 100644 index 2ab728d4113..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bluetp.lua +++ /dev/null @@ -1,14 +0,0 @@ -local greenTp = Action() - -function greenTp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.BlueTel) == -1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a piece of ebony.") - player:addItem(28491, 1) - player:setStorageValue(Storage.TheSecretLibrary.BlueTel, 1) - return true - end - return false -end - -greenTp:uid(1097) -greenTp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_boattp.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_boattp.lua deleted file mode 100644 index 257cb2290f1..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_boattp.lua +++ /dev/null @@ -1,17 +0,0 @@ -local boatTp = Action() - -function boatTp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 4 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The raft was not that solid in the end, its parts are floating in the ocean now. But at least you reached dry land.") - player:removeItem(32407, 1) - player:teleportTo(Position(32187, 32474, 7)) - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 5) - player:setStorageValue(Storage.TheSecretLibrary.PinkTel, 3) - player:setStorageValue(Storage.TheSecretLibrary.Mota, 13) - return true - end - return false -end - -boatTp:uid(1104) -boatTp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bone.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bone.lua deleted file mode 100644 index 2a5244d449b..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bone.lua +++ /dev/null @@ -1,13 +0,0 @@ -local bone = Action() - -function bone.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a reward.") - player:setStorageValue(Storage.TheSecretLibrary.Mota, 2) - return true - end - return false -end - -bone:uid(1083) -bone:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bonedoor.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bonedoor.lua deleted file mode 100644 index a2bf76fd430..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bonedoor.lua +++ /dev/null @@ -1,17 +0,0 @@ -local boneDoor = Action() - -function boneDoor.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 9 then - if target.itemid == 10876 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a reward.") - player:setStorageValue(Storage.TheSecretLibrary.Mota, 10) - player:removeItem(32648, 1) - player:setStorageValue(Storage.TheSecretLibrary.SkullDoor, 1) - end - return true - end - return false -end - -boneDoor:id(1335) -boneDoor:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_book.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_book.lua deleted file mode 100644 index b6ce0469168..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_book.lua +++ /dev/null @@ -1,14 +0,0 @@ -local bookdeepling = Action() - -function bookdeepling.onUse(player, item, frompos, item2, topos) - if player:getStorageValue(Storage.TheSecretLibrary.LiquidDeath) == 1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The descriptions in this book look like plans detailing the launch of a large-scale assault.") - player:setStorageValue(Storage.TheSecretLibrary.LiquidDeath, 2) - else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "oh sorry") - end - return true -end - -bookdeepling:uid(1073) -bookdeepling:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bosses_killed.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bosses_killed.lua deleted file mode 100644 index a62b922469e..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_bosses_killed.lua +++ /dev/null @@ -1,32 +0,0 @@ -local bosses = { - ["ghulosh"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.GhuloshKilled }, - ["gorzindel"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.GorzindelKilled }, - ["lokathmor"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.LokathmorKilled }, - ["mazzinor"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.MazzinorKilled }, - ["scourge of oblivion"] = { storage = Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionKilled }, -} - -local bossesSecretLibrary = CreatureEvent("SecretLibraryBossDeath") -function bossesSecretLibrary.onDeath(creature) - local bossConfig = bosses[creature:getName():lower()] - if not bossConfig then - return true - end - onDeathForDamagingPlayers(creature, function(creature, player) - if bossConfig.storage then - player:setStorageValue(bossConfig.storage, 1) - end - local bossesKilled = 0 - for value in pairs(bosses) do - if player:getStorageValue(bosses[value].storage) > 0 then - bossesKilled = bossesKilled + 1 - end - end - if bossesKilled >= 4 then -- number of mini bosses - player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionDoor, 1) - end - end) - return true -end - -bossesSecretLibrary:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_corpse.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_corpse.lua deleted file mode 100644 index 7f33db76e36..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_corpse.lua +++ /dev/null @@ -1,14 +0,0 @@ -local corpse = Action() - -function corpse.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.TheLament) == 5 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a scribbled notes.") - player:addItem(28515, 1) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 6) - return true - end - return false -end - -corpse:uid(1095) -corpse:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_energybasin.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_energybasin.lua deleted file mode 100644 index 99109f91ebb..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_energybasin.lua +++ /dev/null @@ -1,44 +0,0 @@ -local config = { - -- yellow - [1085] = { - itemId = 27868, - msg = "Success", - storage = Storage.TheSecretLibrary.Mota, - getValue = 4, - setValue = 5, - basin = 3514, - }, - -- green - [1086] = { - itemId = 27867, - msg = "Success", - storage = Storage.TheSecretLibrary.Mota, - getValue = 5, - setValue = 6, - basin = 3514, - }, - -- red - [1087] = { itemId = 27869, msg = "Success", storage = Storage.TheSecretLibrary.Mota, getValue = 6, setValue = 7, basin = 3514 }, -} - -local energyBasin = Action() - -function energyBasin.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local setting = config[item.uid] - if setting then - if player:getStorageValue(setting.storage) == setting.getValue then - player:removeItem(setting.itemId, 1) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, setting.msg) - player:setStorageValue(setting.storage, setting.setValue) - else - player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - end - end - return true -end - -for index, value in pairs(config) do - energyBasin:uid(index) -end - -energyBasin:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_enterlibrary.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_enterlibrary.lua deleted file mode 100644 index a72a30a9289..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_enterlibrary.lua +++ /dev/null @@ -1,15 +0,0 @@ -local blacktp = Action() - -function blacktp.onUse(player, item, frompos, item2, topos) - if player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 5 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Welcome to the Secret Library.") - player:teleportTo(Position(32516, 32537, 12)) - else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "sorry") - end - - return true -end - -blacktp:uid(26705) -blacktp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_eyekey.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_eyekey.lua deleted file mode 100644 index 245b1a0184f..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_eyekey.lua +++ /dev/null @@ -1,14 +0,0 @@ -local eyeKey = Action() - -function eyeKey.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.TheLament) == 4 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a eye key.") - player:addItem(28477, 1) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 5) - return true - end - return false -end - -eyeKey:uid(1094) -eyeKey:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_fish.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_fish.lua deleted file mode 100644 index 0a02d20a344..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_fish.lua +++ /dev/null @@ -1,14 +0,0 @@ -local fish = Action() - -function fish.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a hawser.") - player:addItem(32407, 1) - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 3) - return true - end - return false -end - -fish:uid(1102) -fish:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_greentp.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_greentp.lua deleted file mode 100644 index 306ca25bf81..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_greentp.lua +++ /dev/null @@ -1,14 +0,0 @@ -local greenTp = Action() - -function greenTp.onUse(player, item, frompos, item2, topos) - if player:getStorageValue(Storage.TheSecretLibrary.GreenTel) == -1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You see silver chimes dangling on the dragon statue in this room.") - player:addItem(28494, 1) - player:setStorageValue(Storage.TheSecretLibrary.GreenTel, 1) - return true - end - return false -end - -greenTp:uid(1096) -greenTp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverdoor.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverdoor.lua deleted file mode 100644 index f8cc5d8af77..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverdoor.lua +++ /dev/null @@ -1,14 +0,0 @@ -local leverDoor = Action() - -function leverDoor.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 3 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a reward.") - player:setStorageValue(Storage.TheSecretLibrary.Mota, 4) - player:setStorageValue(Storage.TheSecretLibrary.MotaDoor, 1) - return true - end - return false -end - -leverDoor:uid(1084) -leverDoor:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverruby.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverruby.lua deleted file mode 100644 index c9365895118..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_leverruby.lua +++ /dev/null @@ -1,14 +0,0 @@ -local leverRuby = Action() - -function leverRuby.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 7 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a reward.") - player:addItem(32409, 1) - player:setStorageValue(Storage.TheSecretLibrary.Mota, 8) - return true - end - return false -end - -leverRuby:uid(1088) -leverRuby:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_library_entrances.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_library_entrances.lua deleted file mode 100644 index 7f2565746bc..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_library_entrances.lua +++ /dev/null @@ -1,43 +0,0 @@ -local config = { - { position = { x = 32616, y = 32529, z = 13 }, destination = { x = 32719, y = 32770, z = 10 } }, -- mazzinor - { position = { x = 32718, y = 32768, z = 10 }, destination = { x = 32616, y = 32531, z = 13 } }, - { position = { x = 32724, y = 32728, z = 10 }, destination = { x = 32616, y = 32531, z = 13 } }, - { position = { x = 32660, y = 32736, z = 12 }, destination = { x = 32745, y = 32746, z = 10 } }, -- gorzindel - { position = { x = 32744, y = 32744, z = 10 }, destination = { x = 32660, y = 32734, z = 12 } }, - { position = { x = 32687, y = 32726, z = 10 }, destination = { x = 32660, y = 32734, z = 12 } }, - { position = { x = 32662, y = 32713, z = 13 }, destination = { x = 32745, y = 32770, z = 10 } }, -- ghulosh - { position = { x = 32744, y = 32768, z = 10 }, destination = { x = 32660, y = 32713, z = 13 } }, - { position = { x = 32755, y = 32729, z = 10 }, destination = { x = 32660, y = 32713, z = 13 } }, - { position = { x = 32464, y = 32654, z = 12 }, destination = { x = 32719, y = 32746, z = 10 } }, -- lokathmor - { position = { x = 32718, y = 32744, z = 10 }, destination = { x = 32466, y = 32654, z = 12 } }, - { position = { x = 32750, y = 32696, z = 10 }, destination = { x = 32466, y = 32654, z = 12 } }, - { position = { x = 32480, y = 32601, z = 15 }, destination = { x = 32673, y = 32738, z = 11 } }, -- scourge of oblivion - { position = { x = 32672, y = 32736, z = 11 }, destination = { x = 32480, y = 32599, z = 15 } }, - { position = { x = 32726, y = 32748, z = 11 }, destination = { x = 32480, y = 32599, z = 15 } }, -} - -local libraryEntrances = MoveEvent() -function libraryEntrances.onStepIn(creature, item, position, fromPosition) - local player = creature:getPlayer() - if not player then - return false - end - if player:getLevel() < 250 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need at least level 250 to enter.") - player:teleportTo(fromPosition, true) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - return false - end - for value in pairs(config) do - if Position(config[value].position) == player:getPosition() then - player:teleportTo(Position(config[value].destination)) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - return true - end - end -end - -for value in pairs(config) do - libraryEntrances:position(config[value].position) -end -libraryEntrances:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_lotuskey.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_lotuskey.lua deleted file mode 100644 index 98f3f3c6f1b..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_lotuskey.lua +++ /dev/null @@ -1,14 +0,0 @@ -local lotusKey = Action() - -function lotusKey.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.TheLament) == 3 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a lotus key.") - player:addItem(28476, 1) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 4) - return true - end - return false -end - -lotusKey:uid(1093) -lotusKey:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_peacock.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_peacock.lua deleted file mode 100644 index 48bcfb14f81..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_peacock.lua +++ /dev/null @@ -1,14 +0,0 @@ -local peacock = Action() - -function peacock.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.Peacock) == -1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found the Peacock Ballad.") - player:addItem(28710, 1) - player:setStorageValue(Storage.TheSecretLibrary.Peacock, 1) - return true - end - return false -end - -peacock:uid(1099) -peacock:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_pinktp.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_pinktp.lua deleted file mode 100644 index 204cf10933d..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_pinktp.lua +++ /dev/null @@ -1,14 +0,0 @@ -local blacktp = Action() - -function blacktp.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.PinkTel) == -1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You discovered an old writing desk that contains an ancient map.") - player:addItem(24947, 1) - player:setStorageValue(Storage.TheSecretLibrary.PinkTel, 1) - return true - end - return false -end - -blacktp:uid(1100) -blacktp:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_sealedbook.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_sealedbook.lua deleted file mode 100644 index 8739fea2062..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_sealedbook.lua +++ /dev/null @@ -1,14 +0,0 @@ -local sealedBook = Action() - -function sealedBook.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.PinkTel) == 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a scribbled notes.") - player:addItem(28515, 1) - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 1) - return true - end - return false -end - -sealedBook:uid(1101) -sealedBook:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_skullground.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_skullground.lua deleted file mode 100644 index 7ff399ca43d..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_skullground.lua +++ /dev/null @@ -1,15 +0,0 @@ -local skeleton = Action() - -function skeleton.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.TheLament) == 2 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found an old letter.") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have discovered a skeleton. It seems to hold an old letter and its skull is missing.") - player:addItem(28518, 1) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 3) - return true - end - return false -end - -skeleton:uid(1092) -skeleton:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_statuedeeplings.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_statuedeeplings.lua deleted file mode 100644 index ad186f94e75..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_statuedeeplings.lua +++ /dev/null @@ -1,34 +0,0 @@ -local config = { - [1074] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 2, setValue = 3 }, - [1075] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 3, setValue = 4 }, - [1076] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 4, setValue = 5 }, - [1077] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 5, setValue = 6 }, - [1078] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 6, setValue = 7 }, - [1079] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 7, setValue = 8 }, - [1080] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 8, setValue = 9 }, - [1081] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 9, setValue = 10 }, - [1082] = { itemId = 15895, msg = "The Njey will appreciate your help.", storage = Storage.TheSecretLibrary.LiquidDeath, getValue = 10, setValue = 11 }, -} - -local statuedeeplings = Action() - -function statuedeeplings.onUse(player, item, fromPosition, target, toPosition, isHotkey) - local key = config[item.uid] - if key then - if player:getStorageValue(key.storage) == key.getValue then - if table.contains({ key.itemId }, item.itemid) then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, key.msg) - player:setStorageValue(key.storage, key.setValue) - end - else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Empty.") - end - end - return true -end - -for index, value in pairs(config) do - statuedeeplings:uid(index) -end - -statuedeeplings:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_strandhair.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_strandhair.lua deleted file mode 100644 index 7dfda7e1ed7..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_strandhair.lua +++ /dev/null @@ -1,14 +0,0 @@ -local strandHair = Action() - -function strandHair.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.TheLament) == 1 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a strand of hair.") - player:addItem(28490, 1) - player:setStorageValue(Storage.TheSecretLibrary.TheLament, 2) - return true - end - return false -end - -strandHair:uid(1091) -strandHair:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_telescop.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_telescop.lua deleted file mode 100644 index f53d2c875f6..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/actions_telescop.lua +++ /dev/null @@ -1,13 +0,0 @@ -local telescop = Action() - -function telescop.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 3 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "By using the telescope you observate the stellar constellations. This should help you to navigate your way back to mainland.") - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 4) - return true - end - return false -end - -telescop:uid(1103) -telescop:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_bony_rod.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_bony_rod.lua new file mode 100644 index 00000000000..56b8bd51eef --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_bony_rod.lua @@ -0,0 +1,29 @@ +local basin = 2113 +local finalBasin = Position(33339, 32117, 10) + +local actions_museum_bony_rod = Action() + +function actions_museum_bony_rod.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item.itemid == 28709 then + if target.itemid == 27847 then + item:remove(1) + target:remove(1) + player:addItem(28708, 1) + end + elseif item.itemid == 28708 then + if target.itemid == basin then + item:setAttribute(ITEM_ATTRIBUTE_DURATION, 15 * 1000) + player:say("Recharging...", TALKTYPE_MONSTER_SAY) + else + if target:getPosition() == finalBasin and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.FinalBasin) ~= 1 then + target:getPosition():sendMagicEffect(CONST_ME_DRAWBLOOD) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.FinalBasin, 1) + end + end + end + + return true +end + +actions_museum_bony_rod:id(28708, 28709) +actions_museum_bony_rod:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_doors.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_doors.lua new file mode 100644 index 00000000000..acebff7a338 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_doors.lua @@ -0,0 +1,27 @@ +local doors = { + [1] = { doorPosition = Position(33246, 32122, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, value = 2 }, + [2] = { doorPosition = Position(33208, 32071, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.LeverPermission, value = 1 }, + [3] = { doorPosition = Position(33208, 32074, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.LeverPermission, value = 1 }, + [4] = { doorPosition = Position(33341, 32117, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.FinalBasin, value = 1 }, + [5] = { doorPosition = Position(33344, 32120, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.SkullSample, value = 1 }, +} + +local actions_museum_doors = Action() + +function actions_museum_doors.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, p in pairs(doors) do + if (item:getPosition() == p.doorPosition) and not (Tile(item:getPosition()):getTopCreature()) then + if player:getStorageValue(p.storage) >= p.value then + player:teleportTo(toPosition, true) + item:transform(item.itemid + 1) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The door seems to be sealed against unwanted intruders.") + end + end + end + + return true +end + +actions_museum_doors:aid(4905) +actions_museum_doors:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_gems.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_gems.lua new file mode 100644 index 00000000000..bca9fa38e73 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_gems.lua @@ -0,0 +1,27 @@ +local basins = { + [1] = { position = Position(33219, 32100, 9), item = 27868, storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.YellowGem }, + [2] = { position = Position(33260, 32084, 9), item = 27867, storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.GreenGem }, + [3] = { position = Position(33318, 32090, 9), item = 27869, storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.RedGem }, +} + +local actions_museum_gems = Action() + +function actions_museum_gems.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, p in pairs(basins) do + if p.item == item.itemid then + if player:getStorageValue(p.storage) < 1 then + target:getPosition():sendMagicEffect(CONST_ME_SOUND_PURPLE) + player:setStorageValue(p.storage, 1) + item:remove(1) + end + end + end + + return true +end + +for _, gem in pairs(basins) do + actions_museum_gems:id(gem.item) +end + +actions_museum_gems:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_levers.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_levers.lua new file mode 100644 index 00000000000..83b2be616a8 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_levers.lua @@ -0,0 +1,55 @@ +local boneLever = Position(33204, 32069, 8) +local middleLever = Position(33251, 32039, 8) +local thirdLever = Position(33218, 32096, 10) + +local transform = { + [9110] = 9111, + [9111] = 9110, +} + +local actions_museum_levers = Action() + +function actions_museum_levers.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.LeverPermission) ~= 6 then + if item:getPosition() == boneLever then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 3 then + player:say("You don't know what to do.", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 4) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 5 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.MuseumTimer) > os.time() then + player:say("back, back, up, right, left", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.LeverPermission, 1) + else + player:say("You're too late.", TALKTYPE_MONSTER_SAY) + return true + end + end + elseif item:getPosition() == middleLever then + if item.itemid == 9110 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) == 5 and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.MuseumTimer) < os.time() then + player:say("As you turn the lever you can heart it ticking. Maybe you should hurry up!", TALKTYPE_MONSTER_SAY) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.MuseumTimer, os.time() + 2 * 60) + item:transform(item.itemid + 1) + end + end + end + end + + if item:getPosition() == thirdLever and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.FinalBasin) ~= 1 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.TakenRod) < os.time() then + player:addItem(28709, 1) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.TakenRod, os.time() + 2 * 60) + else + return true + end + end + + if item.itemid == 9110 or item.itemid == 9111 then + item:transform(transform[item:getId()]) + end + + return true +end + +actions_museum_levers:aid(4906) +actions_museum_levers:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_sample_blood.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_sample_blood.lua new file mode 100644 index 00000000000..647e4a5f0e7 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/actions_sample_blood.lua @@ -0,0 +1,15 @@ +local skullPosition = Position(33348, 32117, 10) + +local actions_museum_sample_blood = Action() + +function actions_museum_sample_blood.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if target:getPosition() == skullPosition and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.SkullSample) ~= 1 then + item:remove(1) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.SkullSample, 1) + end + + return true +end + +actions_museum_sample_blood:id(27874) +actions_museum_sample_blood:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/movements_teleportTo.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/movements_teleportTo.lua new file mode 100644 index 00000000000..367698c8dc3 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/bursting_at_the_seams_museum/movements_teleportTo.lua @@ -0,0 +1,67 @@ +local teleports = { + [1] = { fromPos = Position(33246, 32107, 8), toPos = Position(33246, 32096, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, value = 2, nextValue = 3 }, + [2] = { fromPos = Position(33246, 32098, 8), toPos = Position(33246, 32109, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, value = 2 }, +} + +local lastroom_enter = Position(33344, 32117, 10) +local lastroom_exit = Position(33365, 32147, 10) + +local function sendFire(position) + for x = position.x - 1, position.x + 1 do + local newPos = Position(x, position.y, position.z) + newPos:sendMagicEffect(CONST_ME_FIREATTACK) + end +end + +local movements_museum_teleportTo = MoveEvent() + +function movements_museum_teleportTo.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + if item.actionid == 4905 then + for _, p in pairs(teleports) do + if position == p.fromPos then + if player:getStorageValue(p.storage) >= p.value then + player:teleportTo(p.toPos) + sendFire(p.toPos) + if p.nextValue and player:getStorageValue(p.storage) < p.nextValue then + player:setStorageValue(p.storage, p.nextValue) + end + else + player:teleportTo(fromPosition, true) + end + end + end + elseif item.actionid == 4906 then + local hasPermission = false + + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.YellowGem) >= 1 and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.GreenGem) >= 1 and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.RedGem) >= 1 then + hasPermission = true + end + + if not hasPermission then + player:teleportTo(Position(33226, 32084, 9)) + end + elseif item.actionid == 4907 then + if position == lastroom_enter then + player:teleportTo(Position(33363, 32146, 10)) + elseif position == lastroom_exit and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.TrialTimer) < os.time() then + player:teleportTo(Position(33336, 32117, 10)) + else + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline) < 6 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.TrialTimer, os.time() + 3 * 60) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.MoTA.Questline, 6) + player:say("rkawdmawfjawkjnfjkawnkjnawkdjawkfmalkwmflkmawkfnzxc", TALKTYPE_MONSTER_SAY) + end + end + end + + return true +end + +movements_museum_teleportTo:aid(4905, 4906, 4907) +movements_museum_teleportTo:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_falcon_minibosses.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_falcon_minibosses.lua deleted file mode 100644 index 5ed0af0af8a..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_falcon_minibosses.lua +++ /dev/null @@ -1,56 +0,0 @@ -local grandCommanderSoerenDeath = CreatureEvent("GrandCommanderSoerenDeath") -function grandCommanderSoerenDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if killer:isPlayer() and killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCommanderSoeren) < 1 then - killer:setStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCommanderSoeren, 1) - if killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.PreceptorLazare) == 1 then - killer:setStorageValue(Storage.TheSecretLibrary.LowerBastionAccess, 1) -- Access to quest door - end - end -end - -grandCommanderSoerenDeath:register() - -local preceptorLazareDeath = CreatureEvent("PreceptorLazareDeath") -function preceptorLazareDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if killer:isPlayer() and killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.PreceptorLazare) < 1 then - killer:setStorageValue(Storage.TheSecretLibrary.MiniBosses.PreceptorLazare, 1) - if killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCommanderSoeren) == 1 then - killer:setStorageValue(Storage.TheSecretLibrary.LowerBastionAccess, 1) -- Access to quest door - end - end -end - -preceptorLazareDeath:register() - -local grandChaplainGaunderDeath = CreatureEvent("GrandChaplainGaunderDeath") -function grandChaplainGaunderDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if killer:isPlayer() and killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandChaplainGaunder) < 1 then - killer:setStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandChaplainGaunder, 1) - if killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCanonDominus) == 1 then - killer:setStorageValue(Storage.TheSecretLibrary.UndergroundBastionAccess, 1) -- Access to quest door - end - end -end - -grandChaplainGaunderDeath:register() - -local grandCanonDominusDeath = CreatureEvent("GrandCanonDominusDeath") -function grandCanonDominusDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if killer:isPlayer() and killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCanonDominus) < 1 then - killer:setStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandCanonDominus, 1) - if killer:getStorageValue(Storage.TheSecretLibrary.MiniBosses.GrandChaplainGaunder) == 1 then - killer:setStorageValue(Storage.TheSecretLibrary.UndergroundBastionAccess, 1) -- Access to quest door - end - end -end - -grandCanonDominusDeath:register() - -local dazedLeafGolemDeath = CreatureEvent("DazedLeafGolemDeath") -function dazedLeafGolemDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if killer:isPlayer() and killer:getStorageValue(Storage.TheSecretLibrary.OberonAccess) < 1 then - killer:setStorageValue(Storage.TheSecretLibrary.OberonAccess, 1) -- Access to teleport - end -end - -dazedLeafGolemDeath:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_kill.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_kill.lua new file mode 100644 index 00000000000..5a3bde3b049 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_kill.lua @@ -0,0 +1,57 @@ +local defaultTime = 20 + +local creaturescripts_library_bosses = CreatureEvent("killingLibrary") + +function creaturescripts_library_bosses.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified) + if not creature:isMonster() or creature:getMaster() then + return true + end + + local monsterStorages = { + ["grand commander soeren"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 1 }, + ["preceptor lazare"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 2 }, + ["grand chaplain gaunder"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 3 }, + ["grand canon dominus"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 4 }, + ["dazed leaf golem"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 5 }, + ["grand master oberon"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses, value = 6, achievements = { "Millennial Falcon", "Master Debater" }, lastBoss = true }, + ["brokul"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, value = 7 }, + ["the flaming orchid"] = { stg = Storage.Quest.U11_80.TheSecretLibrary.Asuras.FlammingOrchid, value = 1 }, + } + + local monsterName = creature:getName():lower() + local monsterStorage = monsterStorages[monsterName] + + if monsterStorage then + for playerid, damage in pairs(creature:getDamageMap()) do + local p = Player(playerid) + if p then + if p:getStorageValue(monsterStorage.stg) < monsterStorage.value then + p:setStorageValue(monsterStorage.stg, monsterStorage.value) + end + if monsterStorage.achievements then + for i = 1, #monsterStorage.achievements do + p:addAchievement(monsterStorage.achievements[i]) + end + end + if monsterStorage.lastBoss then + if p:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline) < 2 then + p:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.Questline, 2) + end + end + end + end + end + return true +end + +creaturescripts_library_bosses:register() + +local creaturescripts_library_bosses_oberon = CreatureEvent("oberonImmune") + +function creaturescripts_library_bosses_oberon.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) + primaryDamage = 0 + secondaryDamage = 0 + return primaryDamage, primaryType, secondaryDamage, secondaryType +end + +creaturescripts_library_bosses_oberon:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_login.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_login.lua new file mode 100644 index 00000000000..73a1e37c8ce --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/creaturescripts_login.lua @@ -0,0 +1,8 @@ +local creaturescripts_library_login = CreatureEvent("loginLibrary") + +function creaturescripts_library_login.onLogin(player) + player:registerEvent("killingLibrary") + return true +end + +creaturescripts_library_login:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_canon_dominus.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_canon_dominus.lua deleted file mode 100644 index c2527792c0e..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_canon_dominus.lua +++ /dev/null @@ -1,16 +0,0 @@ -local config = { - monsterName = "Grand Canon Dominus", - bossPosition = Position(33384, 31282, 6), - centerPosition = Position(33384, 31282, 6), - rangeX = 50, - rangeY = 50, -} - -local canonDominus = GlobalEvent("canon dominus") -function canonDominus.onThink(interval, lastExecution) - checkBoss(config.centerPosition, config.rangeX, config.rangeY, config.monsterName, config.bossPosition) - return true -end - -canonDominus:interval(15 * 60 * 1000) -canonDominus:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_chaplain_gaunder.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_chaplain_gaunder.lua deleted file mode 100644 index 402005b0aa8..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_chaplain_gaunder.lua +++ /dev/null @@ -1,16 +0,0 @@ -local config = { - monsterName = "Grand Chaplain Gaunder", - bossPosition = Position(33370, 31327, 5), - centerPosition = Position(33370, 31327, 5), - rangeX = 50, - rangeY = 50, -} - -local chaplaingaunder = GlobalEvent("chaplaingaunder") -function chaplaingaunder.onThink(interval, lastExecution) - checkBoss(config.centerPosition, config.rangeX, config.rangeY, config.monsterName, config.bossPosition) - return true -end - -chaplaingaunder:interval(15 * 60 * 1000) -chaplaingaunder:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_commander_soeren.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_commander_soeren.lua deleted file mode 100644 index 64f4ab330e5..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_grand_commander_soeren.lua +++ /dev/null @@ -1,16 +0,0 @@ -local config = { - monsterName = "Grand Commander Soeren", - bossPosition = Position(33376, 31320, 2), - centerPosition = Position(33376, 31320, 2), - rangeX = 50, - rangeY = 50, -} - -local grandCommander = GlobalEvent("grand commander") -function grandCommander.onThink(interval, lastExecution) - checkBoss(config.centerPosition, config.rangeX, config.rangeY, config.monsterName, config.bossPosition) - return true -end - -grandCommander:interval(15 * 60 * 1000) -- 15 minutes -grandCommander:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_preceptor_lazare.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_preceptor_lazare.lua deleted file mode 100644 index ea05353ad09..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_preceptor_lazare.lua +++ /dev/null @@ -1,14 +0,0 @@ -local config = { - monsterName = "Preceptor Lazare", - bossPosition = Position(33374, 31338, 3), - range = 50, -} - -local preceptorLazare = GlobalEvent("PreceptorLazareRespawn") -function preceptorLazare.onThink(interval, lastExecution) - checkBoss(config.bossPosition, config.range, config.range, config.monsterName, config.bossPosition) - return true -end - -preceptorLazare:interval(15 * 60 * 1000) -- 15 minutes -preceptorLazare:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_spawn_damage.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_spawn_damage.lua deleted file mode 100644 index e33a630b556..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/globalevents_secret_library_spawn_damage.lua +++ /dev/null @@ -1,84 +0,0 @@ -local effects = { - { fromPosition = Position(32526, 32536, 12), toPosition = Position(32526, 32539, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32533, 32536, 12), toPosition = Position(32533, 32539, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32540, 32536, 12), toPosition = Position(32540, 32539, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32544, 32542, 12), toPosition = Position(32546, 32542, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32540, 32545, 12), toPosition = Position(32540, 32547, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32533, 32545, 12), toPosition = Position(32533, 32547, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32526, 32545, 12), toPosition = Position(32526, 32547, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32522, 32549, 12), toPosition = Position(32524, 32549, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32522, 32554, 12), toPosition = Position(32524, 32554, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32522, 32559, 12), toPosition = Position(32524, 32559, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32528, 32561, 12), toPosition = Position(32528, 32563, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32535, 32561, 12), toPosition = Position(32535, 32563, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(32542, 32561, 12), toPosition = Position(32542, 32563, 12), effect = CONST_ME_HOLYDAMAGE }, - { fromPosition = Position(33369, 31342, 5), toPosition = Position(33371, 31342, 5), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31334, 5), toPosition = Position(33371, 31334, 5), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33363, 31330, 4), toPosition = Position(33365, 31330, 4), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33363, 31332, 4), toPosition = Position(33365, 31332, 4), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31318, 3), toPosition = Position(33370, 31318, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31322, 3), toPosition = Position(33370, 31322, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31324, 3), toPosition = Position(33370, 31324, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31328, 3), toPosition = Position(33370, 31328, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31330, 3), toPosition = Position(33370, 31330, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31336, 3), toPosition = Position(33370, 31336, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33369, 31339, 3), toPosition = Position(33370, 31339, 3), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33364, 31351, 4), toPosition = Position(33364, 31352, 4), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(33366, 31351, 4), toPosition = Position(33366, 31352, 4), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31716, 31789, 1), toPosition = Position(31716, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31709, 31789, 1), toPosition = Position(31709, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31710, 31789, 1), toPosition = Position(31710, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31703, 31789, 1), toPosition = Position(31703, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31704, 31789, 1), toPosition = Position(31704, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31697, 31789, 1), toPosition = Position(31697, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31698, 31789, 1), toPosition = Position(31698, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31691, 31789, 1), toPosition = Position(31691, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(31692, 31789, 1), toPosition = Position(31692, 31791, 1), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32514, 32610, 12), toPosition = Position(32514, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32515, 32610, 12), toPosition = Position(32515, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32520, 32610, 12), toPosition = Position(32520, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32521, 32610, 12), toPosition = Position(32521, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32526, 32610, 12), toPosition = Position(32526, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32532, 32610, 12), toPosition = Position(32532, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32533, 32610, 12), toPosition = Position(32533, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32538, 32610, 12), toPosition = Position(32538, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32539, 32610, 12), toPosition = Position(32539, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32544, 32610, 12), toPosition = Position(32544, 32612, 12), effect = CONST_ME_FIREAREA }, - { fromPosition = Position(32545, 32610, 12), toPosition = Position(32545, 32612, 12), effect = CONST_ME_FIREAREA }, -} - -local spawnDamage = GlobalEvent("spawn damage") -function spawnDamage.onThink(interval) - local jolf - for i = 1, #effects do - local settings = effects[i] - fromPosition = settings.fromPosition - toPosition = settings.toPosition - local spectators = Game.getSpectators(settings.fromPosition, false, true, 7, 7, 5, 5) - if #spectators > 0 then - if settings.effect then - for y = fromPosition.y, toPosition.y do - local newPosition = Position(fromPosition.x, y, fromPosition.z) - newPosition:sendMagicEffect(settings.effect) - - jolf = Tile(newPosition):getTopCreature() - if jolf and jolf:isPlayer() then - doTargetCombatHealth(0, jolf, COMBAT_PHYSICALDAMAGE, -500, -1000, settings.effect) - end - end - for x = fromPosition.x, toPosition.x do - local newPosition2 = Position(x, fromPosition.y, fromPosition.z) - newPosition2:sendMagicEffect(settings.effect) - jolf = Tile(newPosition2):getTopCreature() - if jolf and jolf:isPlayer() then - doTargetCombatHealth(0, jolf, COMBAT_PHYSICALDAMAGE, -10, -500, settings.effect) - end - end - end - end - end - return true -end - -spawnDamage:interval(9000) -spawnDamage:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/actions_telescope.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/actions_telescope.lua new file mode 100644 index 00000000000..191db8e4cc6 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/actions_telescope.lua @@ -0,0 +1,13 @@ +local actions_isles_telescope = Action() + +function actions_isles_telescope.onUse(player, item, fromPosition, itemEx, toPosition) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.BoatStages) == 2 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.BoatStages, 3) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The telescope provides a perfect view over the endless ocean - no land in sight") + end + + return true +end + +actions_isles_telescope:aid(4935) +actions_isles_telescope:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_boat_puzzle.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_boat_puzzle.lua new file mode 100644 index 00000000000..1e5ac1e9466 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_boat_puzzle.lua @@ -0,0 +1,43 @@ +local movements_isle_color_puzzle = MoveEvent() + +function movements_isle_color_puzzle.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + local boatStage = player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.BoatStages) + + if item.actionid == 4936 then + if boatStage < 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You see the scattered parts of a wrecked ship. Miraculously the ship telescope survived the wreckm it seems still to be intact.") + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.BoatStages, 1) + elseif boatStage >= 1 and boatStage < 2 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There are still some loose planks and hawsers. You can't use the raft like this, it will sink for sure.") + end + elseif item.actionid == 4937 then + if boatStage <= 1 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Hawser) == 1 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You use the hawser to lash up the loose planks. The raft should be seaworthy now.") + if player:getItemCount(28707) >= 1 then + player:removeItem(28707, 1) + end + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.BoatStages, 2) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You see the scattered parts of a wrecked ship. Miraculously the ship telescope survived the wreck it seems still to be intact.") + end + elseif boatStage == 2 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Witout any points of orientation you will never find your way back. Try to find a way to improve your navigation.") + elseif boatStage == 3 then + player:teleportTo(Position(32187, 32473, 7)) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline) < 3 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Questline, 3) + end + end + end + + return true +end + +movements_isle_color_puzzle:aid(4936, 4937) +movements_isle_color_puzzle:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_stepIn.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_stepIn.lua new file mode 100644 index 00000000000..24e6580bf62 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/high_and_dry_isles/movements_stepIn.lua @@ -0,0 +1,100 @@ +local raxias = { + position = Position(33465, 32157, 7), + fromPos = Position(33454, 32151, 8), + toPos = Position(33477, 32171, 8), + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.RaxiasTimer, + exit = Position(33462, 32159, 7), + toPosition = Position(33466, 32156, 8), + bossName = "Raxias", + bossPos = Position(33466, 32161, 8), +} + +local turtle = { + fromPosition = Position(32460, 32928, 7), + toPosition = Position(32316, 32701, 7), + storageTimer = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Turtle, +} + +local svargrond = { + fromPosition = Position(32119, 31734, 7), + toPosition = Position(32127, 31665, 7), +} + +local defaultMessage = "You have ten minutes to kill and loot this monster, else you will lose that chance and will be kicked out." + +local function resetRoom(position) + local spec = Game.getSpectators(position, false, false, 5, 5, 5, 5) + for _, c in pairs(spec) do + if c and c:isPlayer() then + return false + end + end + + for _, c in pairs(spec) do + if c then + c:remove() + end + end + + return true +end + +local function startBattle(pid, position, b_name, middle) + local player = Player(pid) + + if player then + player:teleportTo(position) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + player:say(defaultMessage, TALKTYPE_MONSTER_SAY) + local monster = Game.createMonster(b_name, middle) + end +end + +local movements_isle_stepIn = MoveEvent() + +function movements_isle_stepIn.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + if position == turtle.fromPosition then + if Game.getStorageValue(turtle.storageTimer) > os.time() then + player:teleportTo(turtle.toPosition) + else + player:say("The turtle is hungry... You must feed it.", TALKTYPE_MONSTER_SAY) + player:teleportTo(fromPosition, true) + end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + elseif position == svargrond.fromPosition then + player:teleportTo(svargrond.toPosition) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + elseif position == raxias.position then + if resetRoom(raxias.bossPos) then + if player:getStorageValue(raxias.storage) < os.time() then + startBattle(player:getId(), raxias.toPosition, raxias.bossName, raxias.bossPos) + player:setStorageValue(raxias.storage, os.time() + 20 * 60 * 60) + addEvent(function(cid) + local p = Player(cid) + if p then + if p:getPosition():isInRange(raxias.fromPos, raxias.toPos) then + p:teleportTo(raxias.exit) + end + end + end, 10 * 1000 * 60, player:getId()) + else + player:sendCancelMessage("You are still exhausted from your last battle.") + player:teleportTo(fromPosition, true) + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must wait. Someone is challenging " .. raxias.bossName .. " now.") + player:teleportTo(fromPosition, true) + end + end + + return true +end + +movements_isle_stepIn:aid(4935) +movements_isle_stepIn:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_bossesLever.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_bossesLever.lua new file mode 100644 index 00000000000..6f579ea8e07 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_bossesLever.lua @@ -0,0 +1,167 @@ +local mazzinorSummons = { + name = "Wild Knowledge", + eventName = "mazzinorDeath", + middlePosition = Position(32724, 32720, 10), + timing = 25, + positions = { + [1] = Position(32719, 32718, 10), + [2] = Position(32723, 32719, 10), + [3] = Position(32728, 32718, 10), + [4] = Position(32724, 32724, 10), + }, +} + +local ghuloshSummons = { + name = "Bone Jaw", + eventName = "", + middlePosition = Position(32756, 32721, 10), + timing = 25, + positions = { + [1] = Position(32755, 32721, 10), + }, +} + +local gorzindelSummons = { + name = "Mean Minion", + name2 = "Malicious Minion", + eventName = "", + middlePosition = Position(32687, 32719, 10), + timing = 25, + positions = { + [1] = Position(32687, 32717, 10), + }, + positions2 = { + [1] = Position(32687, 32720, 10), + }, + tomesPosition = { + [1] = { name = "stolen knowledge of armor", position = Position(32687, 32707, 10) }, + [2] = { name = "stolen knowledge of summoning", position = Position(32698, 32715, 10) }, + [3] = { name = "stolen knowledge of lifesteal", position = Position(32693, 32729, 10) }, + [4] = { name = "stolen knowledge of spells", position = Position(32681, 32729, 10) }, + [5] = { name = "stolen knowledge of healing", position = Position(32676, 32715, 10) }, + }, +} + +local lokathmorSummons = { + name = "Knowledge Raider", + eventName = "", + middlePosition = Position(32751, 32689, 10), + timing = 25, + positions = { + [1] = Position(32747, 32684, 10), + [2] = Position(32755, 32684, 10), + [3] = Position(32755, 32694, 10), + [4] = Position(32747, 32694, 10), + }, +} + +local bossNames = { "mazzinor", "supercharged mazzinor", "lokathmor", "ghulosh", "ghuloshz' deathgaze", "gorzindel", "stolen tome of portals" } + +local function spawnSummons(k, monsterName, eventName, timing, positionTable, middlePosition, isGorzindel) + local spectators = Game.getSpectators(middlePosition, false, false, 12, 12, 12, 12) + local hasPlayer = false + + for _, c in pairs(spectators) do + if c and c:isPlayer() then + hasPlayer = true + end + end + + if isGorzindel then + local hasTome = false + for _, c in pairs(spectators) do + for i = 1, #gorzindelSummons.tomesPosition do + if c and (c:getName():lower() == gorzindelSummons.tomesPosition[i].name) then + hasTome = true + end + end + end + if not hasTome then + return false + end + end + if hasPlayer then + if k <= 4 then + for i = 1, #positionTable do + local sqm = positionTable[i] + if sqm then + sqm:sendMagicEffect(CONST_ME_TELEPORT) + end + end + k = k + 1 + addEvent(spawnSummons, 2 * 1000, k, monsterName, eventName, timing, positionTable, middlePosition, isGorzindel) + else + for i = 1, #positionTable do + local monster = Game.createMonster(monsterName, positionTable[i]) + if monster then + monster:registerEvent(eventName) + end + end + addEvent(function() + spawnSummons(1, monsterName, eventName, timing, positionTable, middlePosition, isGorzindel) + end, timing * 1000) + end + end +end + +local leverInfo = { + [1] = { bossName = "Mazzinor", storage = Storage.Quest.U11_80.TheSecretLibrary.Library.MazzinorTimer, exit = Position(32616, 32532, 13), position = Position(32720, 32773, 10), type = "x", bossPosition = Position(32724, 32720, 10), teleportTo = Position(32724, 32726, 10), fromPosition = Position(32715, 32712, 10), toPosition = Position(32733, 32729, 10) }, + [2] = { bossName = "Lokathmor", storage = Storage.Quest.U11_80.TheSecretLibrary.Library.LokathmorTimer, exit = Position(32467, 32654, 12), position = Position(32720, 32749, 10), type = "x", bossPosition = Position(32751, 32689, 10), teleportTo = Position(32750, 32694, 10), fromPosition = Position(32741, 32680, 10), toPosition = Position(32759, 32697, 10) }, + [3] = { bossName = "Ghulosh", storage = Storage.Quest.U11_80.TheSecretLibrary.Library.GhuloshTimer, exit = Position(32659, 32713, 13), position = Position(32746, 32773, 10), type = "x", bossPosition = Position(32756, 32721, 10), teleportTo = Position(32755, 32727, 10), fromPosition = Position(32745, 32711, 10), toPosition = Position(32768, 32730, 10) }, + [4] = { bossName = "Gorzindel", storage = Storage.Quest.U11_80.TheSecretLibrary.Library.GorzindelTimer, exit = Position(32660, 32734, 12), position = Position(32746, 32749, 10), type = "x", bossPosition = Position(32685, 32717, 10), teleportTo = Position(32687, 32724, 10), fromPosition = Position(32671, 32703, 10), toPosition = Position(32702, 32734, 10) }, +} + +local actions_library_bossesLever = Action() + +function actions_library_bossesLever.onUse(player, item, fromPosition, itemEx, toPosition) + local playersTable = {} + + for _, lever in pairs(leverInfo) do + if toPosition == lever.position then + if player:doCheckBossRoom(lever.bossName, lever.fromPosition, lever.toPosition) then + if lever.type == "x" then + local startPos = lever.position.x + 1 + for x = startPos, startPos + 4 do + local sqm = Tile(Position(x, lever.position.y, lever.position.z)) + if sqm then + local c = sqm:getTopCreature() + if c and c:isPlayer() then + table.insert(playersTable, c:getId()) + c:teleportTo(lever.teleportTo) + c:setStorageValue(lever.storage, os.time() + 20 * 60 * 60) + end + end + end + end + + local monster = Game.createMonster(lever.bossName, lever.bossPosition) + + if monster then + if lever.bossName:lower() == "mazzinor" then + addEvent(spawnSummons, 4 * 1000, 1, mazzinorSummons.name, mazzinorSummons.eventName, mazzinorSummons.timing, mazzinorSummons.positions, mazzinorSummons.middlePosition, false) + elseif lever.bossName:lower() == "lokathmor" then + addEvent(spawnSummons, 4 * 1000, 1, lokathmorSummons.name, lokathmorSummons.eventName, lokathmorSummons.timing, lokathmorSummons.positions, lokathmorSummons.middlePosition, false) + elseif lever.bossName:lower() == "ghulosh" then + addEvent(spawnSummons, 4 * 1000, 1, ghuloshSummons.name, ghuloshSummons.eventName, ghuloshSummons.timing, ghuloshSummons.positions, ghuloshSummons.middlePosition, false) + local book = Game.createMonster("The Book of Death", Position(32755, 32716, 10)) + Game.setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Library.Ghulosh, 1) + elseif lever.bossName:lower() == "gorzindel" then + addEvent(spawnSummons, 4 * 1000, 1, gorzindelSummons.name, gorzindelSummons.eventName, gorzindelSummons.timing, gorzindelSummons.positions, gorzindelSummons.middlePosition, true) + addEvent(spawnSummons, 4 * 1000, 1, gorzindelSummons.name2, gorzindelSummons.eventName, gorzindelSummons.timing, gorzindelSummons.positions2, gorzindelSummons.middlePosition, true) + local tome = Game.createMonster("Stolen Tome of Portals", Position(32688, 32715, 10)) + for _, k in pairs(gorzindelSummons.tomesPosition) do + local monster = Game.createMonster(k.name, k.position) + local minion = Game.createMonster("Malicious Minion", k.position) + end + end + end + addEvent(kickPlayersAfterTime, 30 * 60 * 1000, playersTable, lever.fromPosition, lever.toPosition, lever.exit) + end + end + end + + return true +end + +actions_library_bossesLever:aid(4950) +actions_library_bossesLever:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_parchment.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_parchment.lua new file mode 100644 index 00000000000..1ffb6414c4c --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/actions_parchment.lua @@ -0,0 +1,54 @@ +local deskPosition = Position(32743, 32689, 10) +local center = Position(32751, 32689, 10) + +local function isStuck(mustFree) + local c = Tile(center):getTopCreature() + + if c and c:isMonster() then + if c:getName():lower() == "lokathmor" and c:getSpeed() == 0 then + if mustFree then + c:say("THE DISCHARGE OF THE BOOK BREAKS LOKATHMORS STANCE!", TALKTYPE_MONSTER_SAY) + local cHealth = c:getHealth() + local monster = Game.createMonster("Lokathmor", center, true) + c:remove() + if monster then + monster:addHealth(-(monster:getHealth() - cHealth)) + end + else + return true + end + end + end + + return false +end + +local function freeRoom() + local spectators = Game.getSpectators(center, false, false, 9, 9, 9, 9) + for _, p in pairs(spectators) do + if p and p:isMonster() then + if p:getName():lower() == "force field" then + p:remove() + end + end + end + + isStuck(true) +end + +local actions_library_parchment = Action() + +function onUse(player, item, fromPosition, target, toPosition, isHotkey) + if toPosition == deskPosition then + if isStuck(false) then + player:say("THE DARK KNOWLEDGE PILLS THE BOOK WITH RAW POWER. READY TO BE UNLEASHED!", TALKTYPE_MONSTER_SAY) + freeRoom() + item:remove(1) + end + end + + return true +end + +actions_library_parchment:id(28488) +actions_library_parchment:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_ghulosh.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_ghulosh.lua new file mode 100644 index 00000000000..649217a86f5 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_ghulosh.lua @@ -0,0 +1,67 @@ +local info = { + stages = { + { p = 75, v = 1 }, + { p = 50, v = 2 }, + { p = 25, v = 3 }, + }, + stg = Storage.Quest.U11_80.TheSecretLibrary.Library.Ghulosh, +} + +local function nextStage(storage) + if Game.getStorageValue(storage) < 1 then + Game.setStorageValue(storage, 1) + end + Game.setStorageValue(storage, Game.getStorageValue(storage) + 1) +end + +local creaturescripts_library_ghulosh = CreatureEvent("ghuloshThink") + +function creaturescripts_library_ghulosh.onThink(creature, interval) + local stage = 0 + + for _, k in pairs(info.stages) do + if Game.getStorageValue(info.stg) == k.v then + stage = k.p + end + end + + local position = creature:getPosition() + local cHealth = creature:getHealth() + local percentageHealth = (cHealth / creature:getMaxHealth()) * 100 + + if percentageHealth <= stage then + local monster = Game.createMonster("ghulosh' deathgaze", position, true) + nextStage(info.stg) + creature:remove() + if monster then + monster:addHealth(-(monster:getHealth() - cHealth)) + monster:say("FEEL MY WRATH!!", TALKTYPE_MONSTER_SAY) + end + end +end + +creaturescripts_library_ghulosh:register() + +local function doSpawn(monster, k, position) + if k <= 4 then + position:sendMagicEffect(CONST_ME_TELEPORT) + k = k + 1 + addEvent(doSpawn, 2 * 1000, monster, k, position) + else + local monster = Game.createMonster(monster, position) + end +end + +local creaturescripts_library_ghulosh = CreatureEvent("ghuloshDeath") + +function creaturescripts_library_ghulosh.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) + local cPos = creature:getPosition() + + if creature:getName():lower() == "the book of death" then + Game.createMonster("Concentrated Death", cPos) + elseif creature:getName():lower() == "concentrated death" then + addEvent(doSpawn, 4 * 1000, "The Book of Death", 1, Position(32755, 32716, 10)) + end +end + +creaturescripts_library_ghulosh:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_gorzindel.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_gorzindel.lua new file mode 100644 index 00000000000..37d11f35a9a --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_gorzindel.lua @@ -0,0 +1,63 @@ +local knowledges = { + "stolen knowledge of armor", + "stolen knowledge of summoning", + "stolen knowledge of lifesteal", + "stolen knowledge of spells", + "stolen knowledge of healing", +} + +local middlePosition = Position(32687, 32719, 10) + +local creaturescripts_gorzindel = CreatureEvent("gorzindelDeath") + +function creaturescripts_gorzindel.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) + local cPos = creature:getPosition() + + if isInArray(knowledges, creature:getName():lower()) then + addEvent(function() + local spectators = Game.getSpectators(middlePosition, false, false, 12, 12, 12, 12) + local hasKnowledges = false + for _, c in pairs(spectators) do + if c and isInArray(knowledges, c:getName():lower()) then + hasKnowledges = true + end + end + if not hasKnowledges then + for _, c in pairs(spectators) do + if c then + if c:getName():lower() == "mean minion" then + c:getPosition():sendMagicEffect(CONST_ME_POFF) + c:remove() + elseif c:getName():lower() == "gorzindel" then + c:unregisterEvent("gorzindelHealth") + end + end + end + end + end, 1 * 1000) + elseif creature:getName():lower() == "stolen tome of portals" then + local portal = Game.createItem(1949, 1, cPos) + if portal then + portal:setActionId(4952) + addEvent(function() + Game.createMonster("stolen tome of portals", cPos, true, true) + local sqm = Tile(cPos):getItemById(1949) + if sqm then + sqm:remove(1) + end + end, 10 * 1000) + end + end +end + +creaturescripts_gorzindel:register() + +local creaturescripts_gorzindel = CreatureEvent("gorzindelHealth") + +function creaturescripts_gorzindel.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) + primaryDamage = 0 + secondaryDamage = 0 + return primaryDamage, primaryType, secondaryDamage, secondaryType +end + +creaturescripts_gorzindel:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_lokathmor.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_lokathmor.lua new file mode 100644 index 00000000000..b01ec8373c5 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_lokathmor.lua @@ -0,0 +1,12 @@ +local paper = 28488 + +local creaturescripts_library_lokathmor = CreatureEvent("lokathmorDeath") + +function creaturescripts_library_lokathmor.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) + local cPos = creature:getPosition() + if creature:getName():lower() == "dark knowledge" then + local item = Game.createItem(paper, 1, cPos) + end +end + +creaturescripts_library_lokathmor:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_mazzinor.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_mazzinor.lua new file mode 100644 index 00000000000..1931906f9bb --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/creaturescripts_mazzinor.lua @@ -0,0 +1,33 @@ +local vortexId = 28673 +local actionId = 4951 + +local creaturescripts_library_mazzinor = CreatureEvent("mazzinorDeath") + +function creaturescripts_library_mazzinor.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) + local cPos = creature:getPosition() + if creature:getName():lower() == "wild knowledge" then + local vortex = Game.createItem(vortexId, 1, cPos) + if vortex then + vortex:setActionId(actionId) + addEvent(function(cPos) + local item = Tile(cPos):getItemById(vortexId) + if item then + item:remove() + end + end, 1 * 1000 * 60, cPos) + end + end +end + +creaturescripts_library_mazzinor:register() + +local creaturescripts_library_mazzinor = CreatureEvent("mazzinorHealth") + +function creaturescripts_library_mazzinor.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) + creature:addHealth(primaryDamage or secondaryDamage) + primaryDamage = 0 + secondaryDamage = 0 + return primaryDamage, primaryType, secondaryDamage, secondaryType +end + +creaturescripts_library_mazzinor:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_gorzindel.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_gorzindel.lua new file mode 100644 index 00000000000..8ecf9f94ecd --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_gorzindel.lua @@ -0,0 +1,39 @@ +local tomesPosition = { + [1] = { position = Position(32687, 32707, 10), open = true }, + [2] = { position = Position(32698, 32715, 10), open = true }, + [3] = { position = Position(32693, 32729, 10), open = true }, + [4] = { position = Position(32681, 32729, 10), open = true }, + [5] = { position = Position(32676, 32715, 10), open = true }, +} + +local middlePosition = Position(32687, 32719, 10) + +local movements_library_gorzindel = MoveEvent() + +function movements_library_gorzindel.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + for _, k in pairs(tomesPosition) do + if k.open then + player:teleportTo(k.position) + k.open = false + addEvent(function(cid) + local p = Player(cid) + if p then + p:teleportTo(middlePosition) + k.open = true + end + end, 10 * 1000, player:getId()) + break + end + end + + return true +end + +movements_library_gorzindel:aid(4952) +movements_library_gorzindel:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_mazzinor.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_mazzinor.lua new file mode 100644 index 00000000000..aadc7528105 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_mazzinor.lua @@ -0,0 +1,21 @@ +local outfit = createConditionObject(CONDITION_OUTFIT) +setConditionParam(outfit, CONDITION_PARAM_TICKS, 30 * 1000) +addOutfitCondition(outfit, { lookType = 1065 }) + +local movements_library_mazzinor = MoveEvent() + +function movements_library_mazzinor.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + creature:addCondition(outfit) + creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The remains deporalize you temporaly.") + creature:getPosition():sendMagicEffect(CONST_ME_ENERGYHIT) + item:remove(1) + + return true +end + +movements_library_mazzinor:aid(4951) +movements_library_mazzinor:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_timers.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_timers.lua new file mode 100644 index 00000000000..8a6f6f9a134 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/library_area/movements_timers.lua @@ -0,0 +1,37 @@ +local timers = { + [1] = { position = Position(32616, 32529, 13), timer = Storage.Quest.U11_80.TheSecretLibrary.Library.MazzinorTimer, toPosition = Position(32720, 32770, 10) }, + [2] = { position = Position(32464, 32654, 12), timer = Storage.Quest.U11_80.TheSecretLibrary.Library.LokathmorTimer, toPosition = Position(32720, 32746, 10) }, + [3] = { position = Position(32662, 32713, 13), timer = Storage.Quest.U11_80.TheSecretLibrary.Library.GhuloshTimer, toPosition = Position(32746, 32770, 10) }, + [4] = { position = Position(32660, 32736, 12), timer = Storage.Quest.U11_80.TheSecretLibrary.Library.GorzindelTimer, toPosition = Position(32746, 32746, 10) }, + [5] = { position = Position(32750, 32696, 10), toPosition = Position(32466, 32652, 12) }, + [6] = { position = Position(32755, 32729, 10), toPosition = Position(32664, 32711, 13) }, + [7] = { position = Position(32687, 32726, 10), toPosition = Position(32662, 32734, 12) }, + [8] = { position = Position(32724, 32728, 10), toPosition = Position(32618, 32527, 13) }, +} + +local movements_library_timers = MoveEvent() + +function movements_library_timers.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + for _, k in pairs(timers) do + if position == k.position then + if not k.timer or player:getStorageValue(k.timer) <= os.time() then + player:teleportTo(k.toPosition) + else + player:teleportTo(fromPosition, true) + player:sendCancelMessage("You are still exhausted from your last battle.") + end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + end + end + + return true +end + +movements_library_timers:aid(4950) +movements_library_timers:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_brokulLever.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_brokulLever.lua new file mode 100644 index 00000000000..89c8ac4c479 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_brokulLever.lua @@ -0,0 +1,32 @@ +local config = { + boss = { + name = "Brokul", + position = Position(33483, 31437, 15), + }, + timeToFightAgain = 20 * 60 * 60, + minPlayers = 5, + playerPositions = { + { pos = Position(33522, 31465, 15), teleport = Position(33484, 31446, 15) }, + { pos = Position(33520, 31465, 15), teleport = Position(33484, 31446, 15) }, + { pos = Position(33521, 31465, 15), teleport = Position(33484, 31446, 15) }, + { pos = Position(33523, 31465, 15), teleport = Position(33484, 31446, 15) }, + { pos = Position(33524, 31465, 15), teleport = Position(33484, 31446, 15) }, + }, + specPos = { + from = Position(33472, 31427, 15), + to = Position(33496, 31450, 15), + }, + exit = Position(33528, 31464, 14), + onUseExtra = function(creature, infoPositions) + if creature and creature:isPlayer() then + if creature:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) >= 6 then + return true + end + return false + end + end, +} + +local leverBrokul = BossLever(config) +leverBrokul:aid(34000) +leverBrokul:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_usableItens.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_usableItens.lua new file mode 100644 index 00000000000..168e841886a --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/actions_usableItens.lua @@ -0,0 +1,89 @@ +local config = { + statues = { + [1] = { position = Position(33598, 31398, 14), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue1 }, + [2] = { position = Position(33602, 31439, 13), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue2 }, + [3] = { position = Position(33587, 31461, 14), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue3 }, + [4] = { position = Position(33588, 31461, 14), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue4 }, + [5] = { position = Position(33549, 31459, 14), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue5 }, + [6] = { position = Position(33577, 31475, 15), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue6 }, + [7] = { position = Position(33612, 31465, 15), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue7 }, + [8] = { position = Position(33565, 31423, 13), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue8 }, + [9] = { position = Position(33574, 31441, 15), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Statue9 }, + }, + bookInfo = { + id = 14072, + position = Position(32881, 32435, 8), + storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, + value = 2, + message = "The descriptions in this book look like plans detailing the launch of a large-scale assault.", + }, + statueEffect = CONST_ME_THUNDER, + statueMessage = "The Njey will appreciate your help.", + statueMessage_ = "You recently fixed that idol.", + statueId = { 15895, 15896 }, + fixedId = { 15894, 15897 }, + countStatues = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.StatueCount, + maxValue = 9, +} + +local function doRevert(position, id, newId) + local item = Tile(position):getItemById(newId) + if item then + item:transform(id) + end +end + +local function fixStatue(position, id) + local item = Tile(position):getItemById(id) + local newId = 0 + + if id == config.statueId[1] then + newId = config.fixedId[1] + else + newId = config.fixedId[2] + end + + if item then + item:transform(newId) + position:sendMagicEffect(config.statueEffect) + end + + addEvent(doRevert, 10 * 1000, position, id, newId) +end + +local actions_liquid_usableItens = Action() + +function actions_liquid_usableItens.onUse(player, item, position, fromPosition, pos, target, toPosition) + local b = config.bookInfo + + if item:getId() == b.id and item:getPosition() == b.position then + if player:getStorageValue(b.storage) == b.value then + player:setStorageValue(b.storage, player:getStorageValue(b.storage) + 1) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, b.message) + end + else + local statueId = config.statueId + if item.itemid == statueId[1] or item.itemid == statueId[2] then + for _, k in pairs(config.statues) do + if position == k.position then + if player:getStorageValue(k.storage) < 1 then + player:setStorageValue(k.storage, 1) + player:setStorageValue(config.countStatues, math.max(player:getStorageValue(config.countStatues), 0) + 1) + if player:getStorageValue(config.countStatues) == config.maxValue then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline) + 1) + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, config.statueMessage) + fixStatue(position, item.itemid) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, config.statueMessage_) + end + end + end + end + end + + return true +end + +actions_liquid_usableItens:aid(4900) +actions_liquid_usableItens:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_bossWay.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_bossWay.lua new file mode 100644 index 00000000000..becc6a05cb7 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_bossWay.lua @@ -0,0 +1,41 @@ +local config = { + accesses = { + [1] = { fromPos = Position(33525, 31464, 14), toPos = Position(33525, 31464, 15), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, value = 6, message = "Without the help of other Njey you will probably not make enough of a difference in this battle.", timer = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.BrokulTimer }, + }, + defaultMessage = "You are not ready to pass yet.", + notime = "You need to wait 20 hours to face this boss again.", +} + +local movements_liquid_bossWay = MoveEvent() + +function movements_liquid_bossWay.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + if player then + local accesses = config.accesses + for i = 1, #accesses do + if accesses[i].fromPos == position then + if player:getStorageValue(accesses[i].storage) < accesses[i].value then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, accesses[i].message) + player:teleportTo(fromPosition, true) + else + if player:getStorageValue(accesses[i].timer) > os.time() then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, config.notime) + player:teleportTo(fromPosition, true) + else + player:teleportTo(accesses[i].toPos, true) + end + end + end + end + end + + return true +end + +movements_liquid_bossWay:aid(4901) +movements_liquid_bossWay:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_teleportTo.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_teleportTo.lua new file mode 100644 index 00000000000..f313bf3cdd9 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/liquid_death/movements_teleportTo.lua @@ -0,0 +1,53 @@ +local config = { + teleports = { + [1] = { fromPos = Position(32871, 32510, 7), toPos = Position(32881, 32471, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, value = 1, effect = CONST_ME_WATERSPLASH, achievementName = "Spectulation" }, + [2] = { fromPos = Position(32881, 32473, 9), toPos = Position(32871, 32513, 7), effect = CONST_ME_WATERSPLASH }, + [3] = { fromPos = Position(33584, 31388, 13), toPos = Position(33584, 31391, 13), storage = Storage.Quest.U11_80.TheSecretLibrary.LiquidDeath.Questline, value = 4, effect = CONST_ME_TELEPORT, message = "You squeeze through an ancient small passage. There are small symbols carved deep into the coral you cannot read." }, + [4] = { fromPos = Position(33560, 31395, 13), toPos = Position(33561, 31391, 13), effect = CONST_ME_TELEPORT }, + }, + defaultMessage = "You are not ready to pass yet.", +} + +local movements_liquid_teleportTo = MoveEvent() + +function movements_liquid_teleportTo.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + if player then + for i = 1, #config.teleports do + local tab = config.teleports + if position == tab[i].fromPos then + if tab[i].storage then + if player:getStorageValue(tab[i].storage) >= tab[i].value then + player:teleportTo(tab[i].toPos) + if tab[i].message then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, tab[i].message) + end + if tab[i].achievementName and not player:hasAchievement(tab[i].achievementName) then + player:addAchievement(tab[i].achievementName) + end + if player:getStorageValue(tab[i].storage) == tab[i].value then + player:setStorageValue(tab[i].storage, player:getStorageValue(tab[i].storage) + 1) + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, config.defaultMessage) + player:teleportTo(fromPosition, true) + return true + end + else + player:teleportTo(tab[i].toPos) + end + player:getPosition():sendMagicEffect(tab[i].effect) + end + end + end + + return true +end + +movements_liquid_teleportTo:aid(4900) +movements_liquid_teleportTo:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_boat.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_boat.lua deleted file mode 100644 index d076b5e22f2..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_boat.lua +++ /dev/null @@ -1,17 +0,0 @@ -local boat = MoveEvent() - -function boat.onStepIn(creature, item, toPosition, fromPosition) - local player = creature:getPlayer() - if not player then - return true - end - - if player:getStorageValue(Storage.TheSecretLibrary.HighDry) == 1 then - player:setStorageValue(Storage.TheSecretLibrary.HighDry, 2) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There are still some loose planks and hawsers. You can't use the raft like this, it will sink for sure.") - end - return true -end - -boat:aid(26701) -boat:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_golem_teleport.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_golem_teleport.lua deleted file mode 100644 index c8f53be5453..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_golem_teleport.lua +++ /dev/null @@ -1,17 +0,0 @@ -local golemTeleport = MoveEvent() - -function golemTeleport.onStepIn(creature, item, toPosition, fromPosition) - local player = creature:getPlayer() - if not player then - return true - end - - if player:getStorageValue(Storage.TheSecretLibrary.Mota) == 10 then - player:setStorageValue(Storage.TheSecretLibrary.Mota, 11) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end - return true -end - -golemTeleport:aid(26688) -golemTeleport:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_pink_teleport.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_pink_teleport.lua deleted file mode 100644 index 772926ede5e..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_pink_teleport.lua +++ /dev/null @@ -1,17 +0,0 @@ -local pinkTeleport = MoveEvent() - -function pinkTeleport.onStepIn(creature, item, toPosition, fromPosition) - local player = creature:getPlayer() - if not player then - return true - end - - if player:getStorageValue(Storage.TheSecretLibrary.Peacock) == 2 then - player:teleportTo(Position(32880, 32828, 11)) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - end - return true -end - -pinkTeleport:aid(26698) -pinkTeleport:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_teleport.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_teleport.lua deleted file mode 100644 index e788c64e0a4..00000000000 --- a/data-otservbr-global/scripts/quests/the_secret_library_quest/movements_teleport.lua +++ /dev/null @@ -1,35 +0,0 @@ -local destination = { - [64007] = Position(33345, 31347, 7), --Falcon - [64008] = Position(33357, 31308, 4), --Falcon - [64009] = Position(33382, 31292, 7), --Falcon - [64010] = Position(33327, 31351, 7), --Falcon - [64011] = Position(33201, 31765, 1), --Falcon - [64012] = Position(33327, 31351, 7), --Falcon - [64013] = Position(32958, 32324, 8), --Deep desert - [64014] = Position(33110, 32386, 7), --Deep desert -} - -local teleport = MoveEvent() - -function teleport.onStepIn(creature, item, position, fromPosition) - local player = creature:getPlayer() - if not player then - return true - end - - local teleport = destination[item.actionid] - if teleport then - player:teleportTo(teleport) - fromPosition:sendMagicEffect(CONST_ME_TELEPORT) - teleport:sendMagicEffect(CONST_ME_TELEPORT) - end - return true -end - -teleport:type("stepin") - -for index, value in pairs(destination) do - teleport:aid(index) -end - -teleport:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_bonefiddle.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_bonefiddle.lua new file mode 100644 index 00000000000..1a4ff13266b --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_bonefiddle.lua @@ -0,0 +1,46 @@ +local actions_asura_bonefiddle = Action() + +function actions_asura_bonefiddle.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) < 2 then + if item.itemid == 28491 then + if target.itemid == 28489 then + item:remove(1) + target:remove(1) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You attach the ebony wood to the skull. This should meet the requirements of a fingerboard.") + player:addItem(28492) + end + elseif item.itemid == 28492 then + if target.itemid == 28490 then + item:remove(1) + target:remove(1) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You tack the hair to the ebony fingerboard. The strands should be adquate to serve as strings.") + player:addItem(28493) + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 2) + end + end + end + if item.itemid == 28493 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) == 2 then + if player:getPosition():isInRange(Position(32807, 32762, 10), Position(32809, 32768, 10)) then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 3) + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "*There was once a maiden fair, with dark eyes and silken hair. Far away from home she died. No grave, no wake, no mourning.*") + player:getPosition():sendMagicEffect(CONST_ME_SOUND_PURPLE) + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) == 4 then + if player:getPosition():isInRange(Position(32807, 32762, 10), Position(32809, 32768, 10)) then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are playing the Peacock Ballad and the portal opens.") + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, 5) + player:getPosition():sendMagicEffect(CONST_ME_SOUND_WHITE) + return true + end + elseif player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) >= 5 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are playing the bone fiddle.") + player:getPosition():sendMagicEffect(CONST_ME_SOUND_WHITE) + end + end + + return true +end + +actions_asura_bonefiddle:id(28491, 28492, 28493) +actions_asura_bonefiddle:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_doors.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_doors.lua new file mode 100644 index 00000000000..6b4ee88eb63 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_doors.lua @@ -0,0 +1,28 @@ +local doors = { + [1] = { doorPosition = Position(32962, 32674, 2), storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.FlammingOrchid, value = 1, level = 250 }, + [2] = { doorPosition = Position(32959, 32679, 2), storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline, value = 1 }, +} + +local actions_asura_doors = Action() + +function actions_asura_doors.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, p in pairs(doors) do + if (item:getPosition() == p.doorPosition) and not (Tile(item:getPosition()):getTopCreature()) then + if player:getStorageValue(p.storage) >= p.value then + if not p.level or (p.level and player:getLevel() >= p.level) then + player:teleportTo(toPosition, true) + item:transform(item.itemid + 1) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You do not have enough level.") + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The door seems to be sealed against unwanted intruders.") + end + end + end + + return true +end + +actions_asura_doors:aid(4911) +actions_asura_doors:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_fragrance.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_fragrance.lua new file mode 100644 index 00000000000..e8630e36887 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_fragrance.lua @@ -0,0 +1,12 @@ +local actions_asura_fragrance = Action() + +function actions_asura_fragrance.onUse(player, item, fromPosition, target, toPosition, isHotkey) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Hmmmm, what an infatuating fragrance!") + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Fragrance, os.time() + 10 * 60) + item:remove(1) + + return true +end + +actions_asura_fragrance:id(28495) +actions_asura_fragrance:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_keys.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_keys.lua new file mode 100644 index 00000000000..a259ca202ea --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_keys.lua @@ -0,0 +1,35 @@ +local doors = { + [1] = { key = 28476, position = Position(32813, 32813, 9) }, + [2] = { key = 28477, position = Position(32864, 32810, 9) }, +} + +local locked = 23873 +local opened = 23877 + +local function revert(position) + local lockedDoor = Tile(position):getItemById(opened) + if lockedDoor then + lockedDoor:transform(locked) + end +end + +local actions_asura_keys = Action() + +function actions_asura_keys.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, k in pairs(doors) do + if item.itemid == k.key then + if toPosition == k.position and target.itemid == locked then + target:transform(opened) + addEvent(revert, 10 * 1000, target:getPosition()) + end + end + end + + return true +end + +for _, door in pairs(doors) do + actions_asura_keys:id(door.key) +end + +actions_asura_keys:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_mirror.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_mirror.lua new file mode 100644 index 00000000000..448152746f2 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/actions_mirror.lua @@ -0,0 +1,19 @@ +local goPos = Position(32814, 32754, 9) + +local actions_asura_mirror = Action() + +function actions_asura_mirror.onUse(player, item, fromPosition, itemEx, toPosition) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.FlammingOrchid) >= 1 and player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline) >= 1 then + if player:getLevel() >= 250 then + player:teleportTo(goPos) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + else + player:sendCancelMessage("You do not have enough level.") + end + else + player:sendCancelMessage("You do not have permission.") + end +end + +actions_asura_mirror:aid(4910) +actions_asura_mirror:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/creaturescripts_asuras_mechanic.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/creaturescripts_asuras_mechanic.lua new file mode 100644 index 00000000000..d569a8806f2 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/creaturescripts_asuras_mechanic.lua @@ -0,0 +1,50 @@ +local redItems = { + 3566, + 3379, + 3388, + 8039, + 8053, + 8064, + 22534, + 3381, + 7991, + 3380, + 10439, + 3564, +} + +local creaturescripts_asuras_mechanic = CreatureEvent("AsurasMechanic") + +function creaturescripts_asuras_mechanic.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) + if not attacker or not creature then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + + if attacker:isPlayer() then + if creature:getName():lower() == "the diamond blossom" then + local slot = attacker:getSlotItem(CONST_SLOT_ARMOR) + if slot then + for i = 1, #redItems do + if slot.itemid == redItems[i] then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + end + end + elseif creature:getName():lower() == "the blazing rose" then + local slot = attacker:getSlotItem(CONST_SLOT_RIGHT) + if slot and slot.itemid == 28494 then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + elseif creature:getName():lower() == "the lily of night" then + if attacker:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Asuras.Fragrance) > os.time() then + return primaryDamage, primaryType, secondaryDamage, secondaryType + end + end + end + + primaryDamage = 0 + secondaryDamage = 0 + return primaryDamage, primaryType, secondaryDamage, secondaryType +end + +creaturescripts_asuras_mechanic:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/movements_elemental_portals.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/movements_elemental_portals.lua new file mode 100644 index 00000000000..8776ee64ba3 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_lament_asuras/movements_elemental_portals.lua @@ -0,0 +1,158 @@ +local entrances = { + [1] = { position = Position(32860, 32798, 11), storage = false, toPosition = Position(32887, 32772, 9) }, + [2] = { + position = Position(32858, 32766, 10), + toPosition = Position(32882, 32791, 11), + fromPos = Position(32877, 32790, 11), + toPos = Position(32887, 32800, 11), + exit = Position(32858, 32767, 10), + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.DiamondTimer, + bossName = "the diamond blossom", + bossPos = Position(32882, 32795, 11), + }, + [3] = { + position = Position(32818, 32780, 11), + toPosition = Position(32857, 32740, 11), + fromPos = Position(32852, 32739, 11), + toPos = Position(32862, 32749, 11), + exit = Position(32818, 32781, 11), + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.DarkTimer, + bossName = "the lily of night", + bossPos = Position(32857, 32744, 11), + }, + [4] = { + position = Position(32854, 32737, 10), + toPosition = Position(32860, 32770, 11), + fromPos = Position(32855, 32769, 11), + toPos = Position(32865, 32779, 11), + exit = Position(32854, 32738, 10), + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.BlazingTimer, + bossName = "the blazing rose", + bossPos = Position(32860, 32774, 11), + }, +} +local exits = { + [1] = { position = Position(32857, 32739, 11), toPosition = Position(32818, 32781, 11) }, + [2] = { position = Position(32860, 32769, 11), toPosition = Position(32854, 32738, 10) }, + [3] = { position = Position(32882, 32790, 11), toPosition = Position(32858, 32767, 10) }, + [4] = { position = Position(32886, 32772, 9), toPosition = Position(32860, 32799, 11) }, + [5] = { position = Position(32881, 32829, 11), toPosition = Position(32809, 32765, 10) }, +} +local defaultMessage = "You have ten minutes to kill and loot this monster, else you will lose that chance and will be kicked out." +local purplePosition = Position(32808, 32765, 10) +local quest = Storage.Quest.U11_80.TheSecretLibrary.Asuras.Questline +local toPosition_l = Position(32881, 32828, 11) +local hiddenMap1 = Position(32881, 32820, 11) +local hiddenMap2 = Position(32882, 32820, 11) + +local function isPlayerInRoom(fromPos, toPos) + for x = fromPos.x, toPos.x do + for y = fromPos.y, toPos.y do + for z = fromPos.z, toPos.z do + local tile = Tile(Position(x, y, z)) + if tile then + local creatures = tile:getCreatures() + for _, creature in pairs(creatures) do + if creature:isPlayer() then + return true + end + end + end + end + end + end + return false +end + +local function clearBossRoom(fromPos, toPos, exitPos) + local spectators = Game.getSpectators(fromPos, false, false, 0, 0, 0, 0, toPos) + for _, spec in pairs(spectators) do + if spec:isMonster() then + spec:remove() + end + end +end + +local function startBattle(pid, position, b_name, middle) + local player = Player(pid) + if player then + player:teleportTo(position, true) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + player:say(defaultMessage, TALKTYPE_MONSTER_SAY) + local monster = Game.createMonster(b_name, middle) + end +end + +local function expelPlayerFromRoom(cid, fromPos, toPos, exitPos) + local player = Player(cid) + if player then + if player:getPosition():isInRange(fromPos, toPos) then + player:teleportTo(exitPos) + exitPos:sendMagicEffect(CONST_ME_TELEPORT) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You took too long, the battle has ended.") + end + end +end + +local movements_asura_elemental_portals = MoveEvent() + +function movements_asura_elemental_portals.onStepIn(creature, item, position, fromPosition) + local player = Player(creature:getId()) + + if not creature:isPlayer() then + return false + end + + if item.actionid == 4915 then + if position == purplePosition then + if player:getStorageValue(quest) >= 5 then + player:teleportTo(toPosition_l) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this portal yet.") + player:teleportTo(fromPosition, true) + end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + return true + end + for _, k in pairs(entrances) do + if position == k.position then + if isPlayerInRoom(k.fromPos, k.toPos) then + return true + end + clearBossRoom(k.fromPos, k.toPos, k.exit) + if k.storage then + if player:getStorageValue(k.storage) < os.time() then + startBattle(player:getId(), k.toPosition, k.bossName, k.bossPos) + addEvent(expelPlayerFromRoom, 6000000, player:getId(), k.fromPos, k.toPos, k.exit) + player:setStorageValue(k.storage, os.time() + (20 * 3600)) + else + player:sendCancelMessage("You are still exhausted from your last battle.") + player:teleportTo(fromPosition, true) + end + else + player:teleportTo(k.toPosition) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + end + end + end + elseif item.actionid == 4914 then + if position == hiddenMap1 or hiddenMap2 then + if player:getStorageValue(quest) == 5 then + player:addItem(28908, 1) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have discovered an old writing desk that contains an ancient map.") + player:setStorageValue(quest, 6) + end + end + for _, k in pairs(exits) do + if position == k.position then + player:teleportTo(k.toPosition) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + end + end + end + + return true +end + +movements_asura_elemental_portals:aid(4914, 4915) +movements_asura_elemental_portals:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_doors.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_doors.lua new file mode 100644 index 00000000000..34a56f1d74e --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_doors.lua @@ -0,0 +1,75 @@ +local doors = { + [1] = { doorPosition = Position(33376, 31335, 3), value = 1 }, + [2] = { doorPosition = Position(33371, 31349, 4), value = 2 }, + [3] = { doorPosition = Position(33376, 31349, 4), value = 2 }, + [4] = { doorPosition = Position(33375, 31346, 5), value = 2 }, + [5] = { doorPosition = Position(33363, 31346, 7), value = 4 }, + [6] = { doorPosition = Position(33366, 31343, 7), value = 4 }, +} + +local boats = { + [1] = { + boatPosition = Position(33373, 31309, 7), + value = 3, + toPosition = Position(33382, 31292, 7), + message = "A small island emerges out of the mist as you row towards a tiny light inside a dark, forehoding chapel.", + }, + [2] = { + boatPosition = Position(33382, 31294, 7), + value = 3, + toPosition = Position(33374, 31310, 7), + message = "Your heart lightens as you return from the gloomy isle.", + }, + [3] = { + boatPosition = Position(33344, 31348, 7), + value = 3, + toPosition = Position(33326, 31352, 7), + }, + [4] = { + boatPosition = Position(33328, 31352, 7), + value = 3, + toPosition = Position(33346, 31348, 7), + }, +} + +local actions_falcon_doors = Action() + +function actions_falcon_doors.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if item:getActionId() == 4920 then + for _, p in pairs(doors) do + local door = p.doorPosition + local value = p.value + if (item:getPosition() == door) and not (Tile(item:getPosition()):getTopCreature()) then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses) >= value then + player:teleportTo(toPosition, true) + item:transform(item.itemid + 1) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The door seems to be sealed against unwanted intruders.") + end + end + end + elseif item:getActionId() == 4921 then + for _, p in pairs(boats) do + local boat = p.boatPosition + local value = p.value + local toPos = p.toPosition + local message = p.message + if item:getPosition() == boat then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses) >= value then + player:teleportTo(toPos, true) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + if message then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can not use this boat yet.") + end + end + end + end + + return true +end + +actions_falcon_doors:aid(4920, 4921) +actions_falcon_doors:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_entrance.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_entrance.lua new file mode 100644 index 00000000000..d7601f9ba68 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_entrance.lua @@ -0,0 +1,28 @@ +local actions_entrance = Action() + +function actions_entrance.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if (target == nil) or not target:isItem() then + return false + end + + local currentTime = os.date("*t") + local currentMinute = currentTime.min + + local isNightTime = (currentMinute >= 45 or currentMinute < 15) + + if isNightTime then + if target:getPosition() == Position(33201, 31763, 1) then + player:teleportTo(Position(33356, 31309, 4), true) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Once more you mix the chalk with a drop of your blood and a bit of water and renew the symbol on the floor...") + item:transform(2873, 0) + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use this entrance during the night.") + end + + return true +end + +actions_entrance:id(28468) +actions_entrance:register() diff --git a/data-otservbr-global/scripts/actions/bosses_levers/grand_master_oberon.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_oberonLever.lua similarity index 52% rename from data-otservbr-global/scripts/actions/bosses_levers/grand_master_oberon.lua rename to data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_oberonLever.lua index e7a1a104d52..e736be79de5 100644 --- a/data-otservbr-global/scripts/actions/bosses_levers/grand_master_oberon.lua +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/actions_oberonLever.lua @@ -1,22 +1,26 @@ local config = { boss = { name = "Grand Master Oberon", - position = Position(33364, 31317, 9), + createFunction = function() + Game.createMonster("Grand Master Oberon", Position(33365, 31318, 9), true, true):setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.OberonHeal, 0) + return true + end, }, + timeToFightAgain = 20 * 60 * 60, playerPositions = { + { pos = Position(33364, 31344, 9), teleport = Position(33364, 31322, 9) }, { pos = Position(33362, 31344, 9), teleport = Position(33364, 31322, 9) }, { pos = Position(33363, 31344, 9), teleport = Position(33364, 31322, 9) }, - { pos = Position(33364, 31344, 9), teleport = Position(33364, 31322, 9) }, { pos = Position(33365, 31344, 9), teleport = Position(33364, 31322, 9) }, { pos = Position(33366, 31344, 9), teleport = Position(33364, 31322, 9) }, }, specPos = { - from = Position(33357, 31312, 9), - to = Position(33371, 31324, 9), + from = Position(33356, 31311, 9), + to = Position(33376, 31328, 9), }, - exit = Position(33364, 31341, 9), + exit = Position(33297, 31285, 9), } -local lever = BossLever(config) -lever:aid(57605) -lever:register() +local leverOberon = BossLever(config) +leverOberon:aid(57605) +leverOberon:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/movements_bossEntrance.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/movements_bossEntrance.lua new file mode 100644 index 00000000000..f6068da667b --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_order_of_the_falcon/movements_bossEntrance.lua @@ -0,0 +1,53 @@ +local config = { + entrance = Position(33310, 31325, 8), + exit = Position(33329, 31333, 9), +} + +local movements_falcon_bossEntrance = MoveEvent() + +function movements_falcon_bossEntrance.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local entrance = config.entrance + local exit = config.exit + + if item:getActionId() == 4920 then + if creature then + if item:getPosition() == entrance then + if creature:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.KillingBosses) >= 5 then + creature:teleportTo(Position(exit.x, exit.y - 2, exit.z), true) + else + creature:teleportTo(Position(entrance.x - 2, entrance.y, entrance.z), true) + end + elseif item:getPosition() == exit then + creature:teleportTo(Position(entrance.x - 2, entrance.y, entrance.z), true) + end + end + elseif item:getActionId() == 4921 then + local blockedPositions = { + Position(33328, 31352, 7), + Position(33373, 31309, 7), + Position(33382, 31294, 7), + Position(33344, 31348, 7), + } + if creature then + if isInArray(blockedPositions, position) then + return true + else + if creature:canFightBoss("Grand Master Oberon") then + creature:teleportTo(Position(33363, 31341, 9), true) + else + creature:teleportTo(fromPosition, true) + creature:sendCancelMessage("You are still exhausted from your last battle.") + end + end + end + end + + return true +end + +movements_falcon_bossEntrance:aid(4920, 4921) +movements_falcon_bossEntrance:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_chests.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_chests.lua new file mode 100644 index 00000000000..b11d6209acb --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_chests.lua @@ -0,0 +1,31 @@ +local chests = { + [1] = { position = Position(32970, 32314, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FirstChest, reward = 28538, questlog = true }, + [2] = { position = Position(32980, 32308, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.SecondChest, reward = 28536, questlog = true }, + [3] = { position = Position(32955, 32282, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.ThirdChest, reward = 28537, questlog = false }, + [4] = { position = Position(32983, 32289, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FourthChest, reward = 28535, questlog = false }, + [5] = { position = Position(32944, 32309, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FifthChest, reward = 28818, questlog = true }, +} + +local actions_desert_chests = Action() + +function actions_desert_chests.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, k in pairs(chests) do + if toPosition == k.position then + if player:getStorageValue(k.storage) ~= 1 then + if k.questlog then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline) + 1) + end + player:addItem(k.reward, 1) + player:setStorageValue(k.storage, 1) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have found a " .. ItemType(k.reward):getName():lower() .. ".") + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "It is empty.") + end + end + end + + return true +end + +actions_desert_chests:aid(4931) +actions_desert_chests:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_doors.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_doors.lua new file mode 100644 index 00000000000..be148a3c40e --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_doors.lua @@ -0,0 +1,30 @@ +local doors = { + [1] = { doorPosition = Position(32963, 32319, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.PuzzleSqm, value = 39 }, + [2] = { doorPosition = Position(32955, 32304, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.PuzzleSqm, value = 40 }, + [3] = { doorPosition = Position(32984, 32314, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FirstChest, value = 1 }, + [4] = { doorPosition = Position(32968, 32324, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.SecondChest, value = 1 }, + [5] = { doorPosition = Position(32978, 32290, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.EatenFood, value = 4 }, + [6] = { doorPosition = Position(32963, 32297, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 7 }, + [7] = { doorPosition = Position(32963, 32299, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 7 }, + [8] = { doorPosition = Position(32963, 32301, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 7 }, + [9] = { doorPosition = Position(32963, 32303, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 7 }, +} + +local actions_desert_doors = Action() + +function actions_desert_doors.onUse(player, item, fromPosition, target, toPosition, isHotkey) + for _, p in pairs(doors) do + if (item:getPosition() == p.doorPosition) and not (Tile(item:getPosition()):getTopCreature()) and isInArray({ 8361, 8355, 20450 }, item.itemid) then + if player:getStorageValue(p.storage) >= p.value then + player:teleportTo(toPosition, true) + item:transform(item.itemid + 1) + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The door seems to be sealed against unwanted intruders.") + end + end + end + return true +end + +actions_desert_doors:aid(4930) +actions_desert_doors:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_totems.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_totems.lua new file mode 100644 index 00000000000..86fd5d2edca --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/actions_totems.lua @@ -0,0 +1,54 @@ +local totems = { + { toPosition = Position(32945, 32292, 8), targetId = 28531, toId = 28532, itemId = 28535, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FirstTotem }, + { toPosition = Position(32947, 32292, 8), targetId = 28527, toId = 28528, itemId = 28537, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.SecondTotem }, + { toPosition = Position(32949, 32292, 8), targetId = 28533, toId = 28534, itemId = 28538, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.ThirdTotem }, + { toPosition = Position(32951, 32292, 8), targetId = 28529, toId = 28530, itemId = 28536, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.FourthTotem }, +} + +local function isQuestComplete(cid) + local player = Player(cid) + if player then + for _, s in pairs(totems) do + if player:getStorageValue(s.storage) ~= 1 then + return false + end + end + end + return true +end + +local function revert(old, new, position) + local totem = Tile(position):getItemById(new) + if totem then + totem:transform(old) + end +end + +local actions_desert_totems = Action() + +function actions_desert_totems.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline) == 6 then + for _, k in pairs(totems) do + if toPosition == k.toPosition and item.itemid == k.itemId and target.itemid == k.targetId then + if player:getStorageValue(k.storage) < 1 then + toPosition:sendMagicEffect(CONST_ME_HITAREA) + target:transform(k.toId) + item:remove(1) + player:setStorageValue(k.storage, 1) + addEvent(revert, 15 * 1000, k.targetId, k.toId, toPosition) + end + end + if isQuestComplete(player:getId()) then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, 7) + player:say("Access granted!", TALKTYPE_MONSTER_SAY) + end + end + end + return true +end + +for _, totem in pairs(totems) do + actions_desert_totems:id(totem.itemId) +end + +actions_desert_totems:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_color_puzzle.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_color_puzzle.lua new file mode 100644 index 00000000000..d7b635a9857 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_color_puzzle.lua @@ -0,0 +1,41 @@ +local color = { + [1] = { itemid = 4858, position = Position(32945, 32288, 10), value = 2, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.RedColor }, + [2] = { itemid = 5581, position = Position(32948, 32288, 10), value = 1, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.GreenColor }, + [3] = { itemid = 8695, position = Position(32951, 32288, 10), value = 3, storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.BlueColor }, +} + +local movements_desert_color_puzzle = MoveEvent() + +function movements_desert_color_puzzle.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + local player = Player(creature:getId()) + if player then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.ColorPuzzle) < 1 then + for _, k in pairs(color) do + if item.itemid == k.itemid and position == k.position then + if player:getStorageValue(k.storage) < k.value then + if player:getStorageValue(k.storage) < 0 then + player:setStorageValue(k.storage, 0) + end + player:setStorageValue(k.storage, player:getStorageValue(k.storage) + 1) + else + for i = 1, #color do + player:setStorageValue(color[i].storage, 0) + end + end + end + end + if player:getStorageValue(color[1].storage) == color[1].value and player:getStorageValue(color[2].storage) == color[2].value and player:getStorageValue(color[3].storage) == color[3].value then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.ColorPuzzle, 1) + player:say("Access granted!", TALKTYPE_MONSTER_SAY) + end + end + end + + return true +end + +movements_desert_color_puzzle:aid(4933) +movements_desert_color_puzzle:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_sacrifice_foods.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_sacrifice_foods.lua new file mode 100644 index 00000000000..df06751adcd --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_sacrifice_foods.lua @@ -0,0 +1,237 @@ +local foods = { + 3606, + 3250, + 3577, + 21145, + 21144, + 21143, + 3578, + 3579, + 23535, + 23545, + 3580, + 3581, + 3582, + 3583, + 3584, + 3585, + 3586, + 3587, + 3588, + 3589, + 3590, + 3591, + 3592, + 904, + 3593, + 3594, + 3595, + 3596, + 3597, + 3598, + 3599, + 3600, + 3601, + 3602, + 3607, + 3723, + 3724, + 3725, + 3726, + 3727, + 3728, + 3729, + 3730, + 3731, + 3732, + 5096, + 20310, + 5678, + 6125, + 6277, + 6278, + 6392, + 6393, + 6500, + 6541, + 6542, + 6543, + 6544, + 6545, + 6569, + 6574, + 7158, + 7159, + 229, + 7373, + 7374, + 7375, + 7376, + 7377, + 836, + 841, + 901, + 169, + 8010, + 8011, + 8012, + 8013, + 8014, + 8015, + 8016, + 8017, + 8019, + 8177, + 8197, + 9537, + 10329, + 10453, + 10219, + 11459, + 11460, + 11461, + 11462, + 11681, + 11682, + 11683, + 12310, + 13992, + 14084, + 14085, + 14681, + 15795, + 16103, + 17457, + 17820, + 17821, + 21146, + 22187, + 22185, + 24382, + 24383, + 24396, + 24948, + 25692, + 30198, + 30202, + 31560, + 32069, + 37530, + 37531, + 37532, + 37533, +} + +local pillars = { + { position = Position(32963, 32280, 10), itemPosition = Position(32961, 32280, 10) }, + { position = Position(32963, 32282, 10), itemPosition = Position(32961, 32282, 10) }, + { position = Position(32963, 32284, 10), itemPosition = Position(32961, 32284, 10) }, + { position = Position(32963, 32286, 10), itemPosition = Position(32961, 32286, 10) }, +} + +local storageValue = Storage.Quest.U11_80.TheSecretLibrary.Darashia.EatenFood +local transformTime = 5 * 60 * 1000 + +local perimeter1Min = Position(32964, 32278, 10) +local perimeter1Max = Position(32966, 32290, 10) + +local perimeter2Min = Position(32961, 32288, 10) +local perimeter2Max = Position(32963, 32290, 10) + +local function isFood(itemid) + for _, foodid in ipairs(foods) do + if foodid == itemid then + return true + end + end + return false +end + +local function findPlayerInPerimeter() + -- Verificar ambos os perímetros + for x = perimeter1Min.x, perimeter1Max.x do + for y = perimeter1Min.y, perimeter1Max.y do + local tile = Tile(Position(x, y, perimeter1Min.z)) + if tile then + local player = tile:getTopCreature() + if player and player:isPlayer() then + return player + end + end + end + end + for x = perimeter2Min.x, perimeter2Max.x do + for y = perimeter2Min.y, perimeter2Max.y do + local tile = Tile(Position(x, y, perimeter2Min.z)) + if tile then + local player = tile:getTopCreature() + if player and player:isPlayer() then + return player + end + end + end + end + return nil +end + +local foodSacrifice = MoveEvent() + +function foodSacrifice.onAddItem(moveitem, tileitem, position) + if not isFood(moveitem.itemid) then + return true + end + + for _, pillar in ipairs(pillars) do + if position == pillar.position and tileitem:getActionId() == 4932 then + local itemToTransform = Tile(pillar.itemPosition):getItemById(27987) + if itemToTransform then + -- Transformar item 27987 em 27989 + itemToTransform:transform(27989) + + -- Remover o item de comida e adicionar o item 24490 em seu lugar + local foodPosition = moveitem:getPosition() + moveitem:remove() + Game.createItem(24490, 1, foodPosition) + + addEvent(function() + local revertedTile = Tile(pillar.itemPosition) + if revertedTile then + local itemToRevert = revertedTile:getItemById(27989) + if itemToRevert then + itemToRevert:transform(27987) + end + end + -- Reverter o item 24490 de volta (remover) + local revertFoodItem = Tile(foodPosition):getItemById(24490) + if revertFoodItem then + revertFoodItem:remove() + end + end, transformTime) + + local player = findPlayerInPerimeter() + if player then + local currentProgress = player:getStorageValue(storageValue) + if currentProgress < 0 then + currentProgress = 0 + end + if currentProgress < 4 then + player:setStorageValue(storageValue, currentProgress + 1) + end + if player:getStorageValue(storageValue) == 4 then + if player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Questlog) < 6 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, 6) + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have completed the food offering ritual!") + end + end + + return true + end + end + end + return true +end + +foodSacrifice:type("additem") +foodSacrifice:aid(4932) +foodSacrifice:register() diff --git a/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_teleportTo.lua b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_teleportTo.lua new file mode 100644 index 00000000000..905dcd0e743 --- /dev/null +++ b/data-otservbr-global/scripts/quests/the_secret_library_quest/the_parth_of_defiances_desert/movements_teleportTo.lua @@ -0,0 +1,187 @@ +local lastTeleport = Position(32963, 32312, 8) +local scorpionTimer = Storage.Quest.U11_80.TheSecretLibrary.Darashia.ScorpionTimer +local scorpionPosition = Position(32951, 32309, 8) +local fromPos = Position(32943, 32303, 8) +local toPos = Position(32960, 32315, 8) +local exit = Position(32963, 32307, 8) +local bossName = "furious scorpion" + +local teleports = { + [1] = { position = Position(33110, 32385, 7), destination = Position(32958, 32320, 8), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 1 }, + [2] = { position = Position(32958, 32322, 8), destination = Position(33110, 32387, 7) }, + [3] = { position = Position(32955, 32288, 10), destination = Position(32955, 32284, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.ColorPuzzle, value = 1, challenge = true }, + [4] = { position = Position(32942, 32283, 10), destination = Position(32942, 32288, 10) }, + [5] = { position = Position(32945, 32313, 8), destination = Position(33101, 32381, 7) }, +} + +local tileAccess = { + [1] = { position = Position(32974, 32296, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 2 }, + [2] = { position = Position(32967, 32319, 9), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 3 }, + [3] = { position = Position(32978, 32290, 10), storage = Storage.Quest.U11_80.TheSecretLibrary.Darashia.Questline, value = 6 }, +} + +local puzzle = { + { position = Position(32965, 32310, 9), value = 1 }, + { position = Position(32965, 32309, 9), value = 2 }, + { position = Position(32964, 32309, 9), value = 3 }, + { position = Position(32963, 32309, 9), value = 4 }, + { position = Position(32962, 32309, 9), value = 5 }, + { position = Position(32961, 32309, 9), value = 6 }, + { position = Position(32960, 32309, 9), value = 7 }, + { position = Position(32959, 32309, 9), value = 8 }, + { position = Position(32959, 32310, 9), value = 9 }, + { position = Position(32959, 32311, 9), value = 10 }, + { position = Position(32958, 32311, 9), value = 11 }, + { position = Position(32957, 32311, 9), value = 12 }, + { position = Position(32956, 32311, 9), value = 13 }, + { position = Position(32956, 32310, 9), value = 14 }, + { position = Position(32955, 32310, 9), value = 15 }, + { position = Position(32954, 32310, 9), value = 16 }, + { position = Position(32953, 32310, 9), value = 17 }, + { position = Position(32953, 32311, 9), value = 18 }, + { position = Position(32953, 32312, 9), value = 19 }, + { position = Position(32953, 32313, 9), value = 20 }, + { position = Position(32953, 32314, 9), value = 21 }, + { position = Position(32954, 32314, 9), value = 22 }, + { position = Position(32955, 32314, 9), value = 23 }, + { position = Position(32956, 32314, 9), value = 24 }, + { position = Position(32956, 32315, 9), value = 25 }, + { position = Position(32956, 32316, 9), value = 26 }, + { position = Position(32956, 32317, 9), value = 27 }, + { position = Position(32957, 32317, 9), value = 28 }, + { position = Position(32957, 32318, 9), value = 29 }, + { position = Position(32957, 32319, 9), value = 30 }, + { position = Position(32958, 32319, 9), value = 31 }, + { position = Position(32959, 32319, 9), value = 32 }, + { position = Position(32960, 32319, 9), value = 33 }, + { position = Position(32960, 32318, 9), value = 34 }, + { position = Position(32960, 32317, 9), value = 35 }, + { position = Position(32961, 32317, 9), value = 36 }, + { position = Position(32962, 32317, 9), value = 37 }, + { position = Position(32962, 32318, 9), value = 38 }, + { position = Position(32962, 32319, 9), value = 39 }, +} + +local function startBattle(pid, position, b_name, middle) + local player = Player(pid) + if player then + player:teleportTo(position) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + player:say("You have to master this very last challenge within 5 minutes!", TALKTYPE_MONSTER_SAY) + local monster = Game.createMonster(b_name, middle) + end +end + +local function resetRoom(position, name) + local spec = Game.getSpectators(position, false, false, 5, 5, 5, 5) + + for _, c in pairs(spec) do + if c and c:isPlayer() then + return false + end + end + + for _, c in pairs(spec) do + if c and c:getName():lower() == name then + c:remove() + end + end + + return true +end + +local movements_desert_teleportTo = MoveEvent() + +function movements_desert_teleportTo.onStepIn(creature, item, position, fromPosition) + if not creature:isPlayer() then + return false + end + + local player = Player(creature:getId()) + + if player then + if item.actionid == 4930 then + if position == lastTeleport then + if resetRoom(scorpionPosition, bossName) then + if player:getStorageValue(scorpionTimer) < os.time() then + startBattle(player:getId(), Position(32958, 32309, 8), bossName, scorpionPosition) + addEvent(function(cid) + local p = Player(cid) + if p then + if p:getPosition():isInRange(fromPos, toPos) then + p:teleportTo(exit) + end + end + end, 5 * 1000 * 60, player:getId()) + addEvent(function(cid) + local p = Player(cid) + if p then + p:setStorageValue(scorpionTimer, os.time() + 20 * 60 * 60) + end + end, 1000, player:getId()) + else + player:sendCancelMessage("You are still exhausted from your last battle.") + player:teleportTo(fromPosition, true) + end + else + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must wait. Someone is challenging Furious Scorpion now.") + player:teleportTo(fromPosition, true) + end + else + for _, k in pairs(teleports) do + if position == k.position then + if k.storage then + if player:getStorageValue(k.storage) >= k.value then + player:teleportTo(k.destination) + else + if k.challenge then + player:say("You have to master the challenge first!", TALKTYPE_MONSTER_SAY) + end + player:teleportTo(fromPosition, true) + end + else + player:teleportTo(k.destination) + end + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + end + end + end + elseif item.actionid == 4931 then + local tileItem = Tile(position):getItemById(item.itemid) + if tileItem and (tileItem:getId() == 231 or tileItem:getId() == 28318 or tileItem:getId() == 28319 or tileItem:getId() == 28320 or tileItem:getId() == 28322 or tileItem:getId() == 28323) then + for _, k in pairs(puzzle) do + if position == k.position then + local currentStep = player:getStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.PuzzleSqm) + if currentStep == -1 then + currentStep = 0 + end + if currentStep == k.value - 1 then + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.PuzzleSqm, currentStep + 1) + player:getPosition():sendMagicEffect(CONST_ME_SOUND_WHITE) + + if currentStep + 1 == #puzzle then + player:say("Access granted!", TALKTYPE_MONSTER_SAY) + end + else + player:setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.Darashia.PuzzleSqm, 0) + player:getPosition():sendMagicEffect(CONST_ME_SOUND_RED) + end + end + end + end + elseif item.actionid == 4932 then + for _, k in pairs(tileAccess) do + if position == k.position then + if player:getStorageValue(k.storage) < k.value then + player:setStorageValue(k.storage, player:getStorageValue(k.storage) + 1) + end + end + end + end + end + + return true +end + +movements_desert_teleportTo:aid(4930, 4931, 4932) +movements_desert_teleportTo:register() diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-fairies_release.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_fairies_release.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-fairies_release.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_fairies_release.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-moon_mirror.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_moon_mirror.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-moon_mirror.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_moon_mirror.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-poacher_book.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_poacher_book.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-poacher_book.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_poacher_book.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-poacher_notes.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_poacher_notes.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-poacher_notes.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_poacher_notes.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-starlight_vial.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_starlight_vial.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-starlight_vial.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_starlight_vial.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-sun_catcher.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_sun_catcher.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-sun_catcher.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_sun_catcher.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/action-whelp_fur.lua b/data-otservbr-global/scripts/quests/threatened_dreams/action_whelp_fur.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/action-whelp_fur.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/action_whelp_fur.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/event-raven_herb_bush.lua b/data-otservbr-global/scripts/quests/threatened_dreams/event_raven_herb_bush.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/event-raven_herb_bush.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/event_raven_herb_bush.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/movement-kroazur_room.lua b/data-otservbr-global/scripts/quests/threatened_dreams/movement_kroazur_room.lua similarity index 99% rename from data-otservbr-global/scripts/quests/threatened_dreams/movement-kroazur_room.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/movement_kroazur_room.lua index 46b6a58bd5e..3ca23a4ce84 100644 --- a/data-otservbr-global/scripts/quests/threatened_dreams/movement-kroazur_room.lua +++ b/data-otservbr-global/scripts/quests/threatened_dreams/movement_kroazur_room.lua @@ -1,4 +1,5 @@ local ThreatenedDreams = Storage.Quest.U11_40.ThreatenedDreams + local config = { [25029] = { bossName = "Kroazur", -- boss name diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/movement-poacher_notes.lua b/data-otservbr-global/scripts/quests/threatened_dreams/movement_poacher_notes.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/movement-poacher_notes.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/movement_poacher_notes.lua diff --git a/data-otservbr-global/scripts/quests/threatened_dreams/movement-swan_feathers.lua b/data-otservbr-global/scripts/quests/threatened_dreams/movement_swan_feathers.lua similarity index 100% rename from data-otservbr-global/scripts/quests/threatened_dreams/movement-swan_feathers.lua rename to data-otservbr-global/scripts/quests/threatened_dreams/movement_swan_feathers.lua diff --git a/data-otservbr-global/scripts/spells/monster/exploding_cask.lua b/data-otservbr-global/scripts/spells/monster/exploding_cask.lua index 5448d0733ff..4af10ce98a9 100644 --- a/data-otservbr-global/scripts/spells/monster/exploding_cask.lua +++ b/data-otservbr-global/scripts/spells/monster/exploding_cask.lua @@ -5,7 +5,7 @@ combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA) local combatCast = Combat() -local barrelId = 23485 +local barrelId = 23486 local bombArea = { { 0, 1, 1, 1, 0 }, { 1, 1, 1, 1, 1 }, diff --git a/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua b/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua deleted file mode 100644 index 7da5f5d1b99..00000000000 --- a/data-otservbr-global/scripts/world_changes/iron_servant_transformation.lua +++ /dev/null @@ -1,31 +0,0 @@ -local ironServantTransformation = EventCallback("IronServantTransformationOnSpawn") - -ironServantTransformation.monsterOnSpawn = function(monster, position) - if monster:getName():lower() ~= "iron servant replica" then - return - end - - local chance = math.random(100) - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismDiamond) >= 1 and Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismGolden) >= 1 then - if chance > 30 then - local monsterType = math.random(2) == 1 and "diamond servant replica" or "golden servant replica" - Game.createMonster(monsterType, monster:getPosition(), false, true) - monster:remove() - end - return - end - - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismDiamond) >= 1 and chance > 30 then - Game.createMonster("diamond servant replica", monster:getPosition(), false, true) - monster:remove() - return - end - - if Game.getStorageValue(GlobalStorage.ForgottenKnowledge.MechanismGolden) >= 1 and chance > 30 then - Game.createMonster("golden servant replica", monster:getPosition(), false, true) - monster:remove() - end - return true -end - -ironServantTransformation:register() diff --git a/data-otservbr-global/startup/tables/chest.lua b/data-otservbr-global/startup/tables/chest.lua index d5b28c633ed..c1f15358825 100644 --- a/data-otservbr-global/startup/tables/chest.lua +++ b/data-otservbr-global/startup/tables/chest.lua @@ -181,14 +181,13 @@ ChestUnique = { reward = { { 2970, 1 } }, storage = Storage.Quest.Key.ID3899, }, + -- The Secret Library Quest [5012] = { isKey = true, itemId = 23740, itemPos = { x = 33377, y = 31321, z = 1 }, reward = { { 2969, 1 } }, storage = Storage.Quest.Key.ID0909, - timerStorage = Storage.TheSecretLibrary.FalconBastionChestsTimer.Key0909, - time = 24, -- hour }, -- Bear Room Quest (rookgaard) key 4601 [5013] = { @@ -1080,12 +1079,13 @@ ChestUnique = { weight = 15.00, storage = Storage.Quest.U8_54.TomesOfKnowledge.TopTower, }, + -- The Secret Library Quest [6105] = { itemId = 23741, itemPos = { x = 33352, y = 31318, z = 7 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.Coast, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.Coast, time = 24, -- hour }, [6106] = { @@ -1093,7 +1093,7 @@ ChestUnique = { itemPos = { x = 33384, y = 31285, z = 7 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.Island, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.Island, time = 24, -- hour }, [6107] = { @@ -1101,7 +1101,7 @@ ChestUnique = { itemPos = { x = 33366, y = 31323, z = 5 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.ThroneHall, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.ThroneHall, time = 24, -- hour }, [6108] = { @@ -1109,7 +1109,7 @@ ChestUnique = { itemPos = { x = 33374, y = 31340, z = 4 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.Shortcut, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.Shortcut, time = 24, -- hour }, [6109] = { @@ -1117,7 +1117,7 @@ ChestUnique = { itemPos = { x = 33324, y = 31268, z = 8 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.LowerBastion, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.LowerBastion, time = 24, -- hour }, [6110] = { @@ -1125,7 +1125,7 @@ ChestUnique = { itemPos = { x = 33308, y = 31304, z = 9 }, randomReward = { { 9081, 1 }, { 28821, 1 }, { 28823, 1 }, { 9058, 1 }, { 6299, 1 }, { 3052, 1 }, { 3035, 10 } }, reward = { { nil, nil } }, - timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastionChestsTimer.UndergroundBastion, + timerStorage = Storage.Quest.U11_80.TheSecretLibrary.FalconBastion.ChestsTimer.UndergroundBastion, time = 24, -- hour }, -- Blood Herb Quest @@ -2621,6 +2621,160 @@ ChestUnique = { weight = 1.00, storage = Storage.Quest.U10_90.FerumbrasAscension.VampireTeeth, }, + -- Forgotten Knowledge Quest + [6310] = { + useKV = true, + itemId = 23736, + itemPos = { x = 32825, y = 31664, z = 9 }, + reward = { { 23734, 1 } }, + weight = 6.00, + questName = "GhostsilverLanternQuest", + }, + [6311] = { + useKV = true, + itemId = 21858, + itemPos = { x = 32883, y = 31686, z = 10 }, + reward = { { 23732, 1 } }, + weight = 4.00, + questName = "PaintingOfAGirlQuest", + }, + [6312] = { + useKV = true, + itemId = 9253, + itemPos = { x = 33026, y = 31662, z = 14 }, + reward = { { 24964, 1 } }, + weight = 3.00, + questName = "ImbuingCrystalQuest", + }, + -- Cults of Tibia Quest + [6313] = { + useKV = true, + itemId = 2472, + itemPos = { x = 32739, y = 31426, z = 8 }, + reward = { { 10420, 5 } }, + weight = 8.00, + questName = "PetrifiedScreamQuest", + }, + -- The Secret Library Quest + [6314] = { + itemId = 2472, + itemPos = { x = 33231, y = 32017, z = 8 }, + reward = { { 27874, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.SampleBlood, + }, + [6315] = { + itemId = 2472, + itemPos = { x = 33212, y = 32081, z = 9 }, + reward = { { 27847, 1 } }, + weight = 2.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.BonyRod, + }, + [6316] = { + itemId = 2472, + itemPos = { x = 33342, y = 32120, z = 10 }, + reward = { { 25746, 1 } }, + weight = 2.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.MoTA.BrokenCompass, + }, + [6317] = { + itemId = 28517, + itemPos = { x = 32826, y = 32772, z = 10 }, + reward = { { 28518, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.SkeletonNotes, + }, + [6318] = { + itemId = 28522, + itemPos = { x = 32828, y = 32772, z = 10 }, + reward = { { 28490, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.StrandHair, + }, + [6319] = { + itemId = 1992, + itemPos = { x = 32874, y = 32760, z = 10 }, + reward = { { 28476, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.LotusKey, + }, + [6320] = { + itemId = 27490, + itemPos = { x = 32836, y = 32820, z = 10 }, + reward = { { 28477, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.EyeKey, + }, + [6321] = { + itemId = 6560, + itemPos = { x = 32872, y = 32817, z = 10 }, + reward = { { 28515, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.ScribbledNotes, + }, + [6322] = { + itemId = 4077, + itemPos = { x = 32877, y = 32795, z = 11 }, + reward = { { 28491, 1 } }, + weight = 9.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.EbonyPiece, + }, + [6323] = { + itemId = 23741, + itemPos = { x = 32833, y = 32759, z = 11 }, + reward = { { 28710, 1 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.PeacockBallad, + }, + [6324] = { + itemId = 9794, + itemPos = { x = 32890, y = 32768, z = 9 }, + reward = { { 28494, 1 } }, + weight = 3.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.SilverChimes, + }, + [6325] = { + itemId = 23741, + itemPos = { x = 32852, y = 32744, z = 11 }, + reward = { { 28489, 1 } }, + weight = 20.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.Asuras.BlackSkull, + }, + [6326] = { + itemId = 28828, + itemPos = { x = 32013, y = 32447, z = 8 }, + reward = { { 28650, 1 } }, + weight = 2.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Parchment, + }, + [6327] = { + itemId = 2523, + itemPos = { x = 32096, y = 31757, z = 8 }, + reward = { { 675, 2 } }, + weight = 1.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Sapphire, + }, + [6328] = { + itemId = 4242, + itemPos = { x = 32460, y = 32934, z = 8 }, + reward = { { 3483, 1 } }, + weight = 9.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Fishing, + }, + [6329] = { + itemId = 6560, + itemPos = { x = 32460, y = 32940, z = 7 }, + reward = { { 3457, 1 } }, + weight = 35.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Shovel, + }, + [6330] = { + itemId = 5951, + itemPos = { x = 32025, y = 32469, z = 7 }, + reward = { { 28707, 1 } }, + weight = 6.00, + storage = Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Hawser, + }, -- Reward of others scrips files (varied rewards) -- The First dragon Quest -- Treasure chests (data\scripts\actions\quests\first_dragon\treasure_chests.lua) diff --git a/data-otservbr-global/startup/tables/door_quest.lua b/data-otservbr-global/startup/tables/door_quest.lua index 3e5888b7399..374f3c9a61f 100644 --- a/data-otservbr-global/startup/tables/door_quest.lua +++ b/data-otservbr-global/startup/tables/door_quest.lua @@ -70,26 +70,6 @@ QuestDoorAction = { { x = 33569, y = 31951, z = 14 }, }, }, - -- Secret library quest door - [Storage.TheSecretLibrary.Mota] = { - itemId = false, - itemPos = { - { x = 33208, y = 32071, z = 8 }, - { x = 33246, y = 32122, z = 8 }, - }, - }, - [Storage.TheSecretLibrary.MotaDoor] = { - itemId = false, - itemPos = { { x = 33208, y = 32074, z = 8 } }, - }, - [Storage.TheSecretLibrary.BasinDoor] = { - itemId = false, - itemPos = { { x = 33341, y = 32117, z = 10 } }, - }, - [Storage.TheSecretLibrary.SkullDoor] = { - itemId = false, - itemPos = { { x = 33344, y = 32120, z = 10 } }, - }, -- Koshei the deathless quest door [Storage.Quest.U8_1.KosheiTheDeathless.RewardDoor] = { itemId = false, @@ -203,57 +183,59 @@ QuestDoorAction = { itemPos = { { x = 32067, y = 31896, z = 3 } }, }, -- Cults of tibia door - [Storage.CultsOfTibia.Minotaurs.EntranceAccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Minotaurs.BossAccessDoor] = { itemId = false, - itemPos = { { x = 31950, y = 32501, z = 8 } }, + itemPos = { { x = 31957, y = 32468, z = 9 } }, }, - [Storage.CultsOfTibia.Minotaurs.AccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Minotaurs.AccessDoor] = { itemId = false, - itemPos = { { x = 31957, y = 32468, z = 9 } }, + itemPos = { { x = 31950, y = 32501, z = 8 } }, }, - [Storage.CultsOfTibia.MotA.AccessDoorInvestigation] = { + [Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorInvestigation] = { itemId = false, itemPos = { { x = 33273, y = 32172, z = 8 } }, }, - [Storage.CultsOfTibia.MotA.AccessDoorGareth] = { + [Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorGareth] = { itemId = false, itemPos = { { x = 33220, y = 32147, z = 9 } }, }, - [Storage.CultsOfTibia.MotA.AccessDoorDenominator] = { + [Storage.Quest.U11_40.CultsOfTibia.MotA.AccessDoorDenominator] = { itemId = false, itemPos = { { x = 33220, y = 32149, z = 9 } }, }, - [Storage.CultsOfTibia.Barkless.TrialAccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Barkless.TrialAccessDoor] = { itemId = false, itemPos = { { x = 32688, y = 31543, z = 9 } }, }, - [Storage.CultsOfTibia.Barkless.TarAccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Barkless.TarAccessDoor] = { itemId = false, - itemPos = { - { x = 32747, y = 31462, z = 8 }, - { x = 32678, y = 31506, z = 8 }, - }, + itemPos = { { x = 32747, y = 31462, z = 8 } }, }, - [Storage.CultsOfTibia.Barkless.AccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Barkless.SulphurAccessDoor] = { + itemId = false, + itemPos = { { x = 32678, y = 31506, z = 8 } }, + }, + [Storage.Quest.U11_40.CultsOfTibia.Barkless.AccessDoor] = { itemId = false, itemPos = { - { x = 32742, y = 31408, z = 8 }, { x = 32686, y = 31430, z = 8 }, + { x = 32746, y = 31423, z = 8 }, + { x = 32754, y = 31442, z = 8 }, }, }, - [Storage.CultsOfTibia.Barkless.BossAccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Barkless.BossAccessDoor] = { itemId = false, itemPos = { { x = 32672, y = 31543, z = 9 } }, }, - [Storage.CultsOfTibia.Life.AccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Life.AccessDoor] = { itemId = false, itemPos = { { x = 33295, y = 32271, z = 12 } }, }, - [Storage.CultsOfTibia.Misguided.AccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.Misguided.AccessDoor] = { itemId = false, itemPos = { { x = 32508, y = 32370, z = 9 } }, }, - [Storage.CultsOfTibia.FinalBoss.AccessDoor] = { + [Storage.Quest.U11_40.CultsOfTibia.FinalBoss.AccessDoor] = { itemId = false, itemPos = { { x = 33452, y = 32241, z = 7 } }, }, @@ -794,33 +776,10 @@ QuestDoorAction = { { x = 32012, y = 31565, z = 7 }, }, }, - [Storage.TheSecretLibrary.MiniBosses.PreceptorLazare] = { - itemId = 6260, - itemPos = { { x = 33376, y = 31335, z = 3 } }, - }, - [Storage.TheSecretLibrary.LowerBastionAccess] = { - itemId = 6260, - itemPos = { - { x = 33371, y = 31349, z = 4 }, - { x = 33375, y = 31346, z = 5 }, - }, - }, - [Storage.TheSecretLibrary.UndergroundBastionAccess] = { - itemId = false, - itemPos = { - { x = 33366, y = 31343, z = 7 }, - { x = 33363, y = 31346, z = 7 }, - { x = 32191, y = 31823, z = 8 }, - }, - }, [Storage.Quest.U12_20.GraveDanger.Bosses.KingZelosDoor] = { itemId = false, itemPos = { { x = 32173, y = 31922, z = 8 } }, }, - [Storage.Quest.U11_80.TheSecretLibrary.ScourgeOfOblivionDoor] = { - itemId = false, - itemPos = { { x = 32480, y = 32591, z = 15 } }, - }, [Storage.Quest.U12_70.AdventuresOfGalthen.AccessDoor] = { itemId = false, itemPos = { { x = 32466, y = 32494, z = 8 } }, diff --git a/data-otservbr-global/startup/tables/item.lua b/data-otservbr-global/startup/tables/item.lua index ed01d30aeed..5868efcd31b 100644 --- a/data-otservbr-global/startup/tables/item.lua +++ b/data-otservbr-global/startup/tables/item.lua @@ -556,6 +556,369 @@ ItemAction = { { x = 32994, y = 32442, z = 11 }, }, }, + -- The Secret Library Quest + [4900] = { + itemId = false, + itemPos = { + { x = 32871, y = 32510, z = 7 }, + { x = 32881, y = 32473, z = 9 }, + { x = 32881, y = 32435, z = 8 }, + { x = 33584, y = 31388, z = 13 }, + { x = 33560, y = 31395, z = 13 }, + { x = 33598, y = 31398, z = 14 }, + { x = 33602, y = 31439, z = 13 }, + { x = 33587, y = 31461, z = 14 }, + { x = 33588, y = 31461, z = 14 }, + { x = 33549, y = 31459, z = 14 }, + { x = 33577, y = 31475, z = 15 }, + { x = 33612, y = 31465, z = 15 }, + { x = 33565, y = 31423, z = 13 }, + { x = 33574, y = 31441, z = 15 }, + }, + }, + [4905] = { + itemId = false, + itemPos = { + { x = 33246, y = 32122, z = 8 }, + { x = 33208, y = 32071, z = 8 }, + { x = 33208, y = 32074, z = 8 }, + { x = 33341, y = 32117, z = 10 }, + { x = 33344, y = 32120, z = 10 }, + }, + }, + [4906] = { + itemId = false, + itemPos = { + { x = 33204, y = 32069, z = 8 }, + }, + }, + [4907] = { + itemId = false, + itemPos = { + { x = 33354, y = 32135, z = 10 }, + { x = 33354, y = 32136, z = 10 }, + { x = 33353, y = 32135, z = 10 }, + { x = 33353, y = 32136, z = 10 }, + }, + }, + [4910] = { + itemId = 28906, + itemPos = { + { x = 32953, y = 32669, z = 7 }, + }, + }, + [4911] = { + itemId = false, + itemPos = { + { x = 32962, y = 32674, z = 2 }, + { x = 32959, y = 32679, z = 2 }, + }, + }, + [4914] = { + itemId = false, + itemPos = { + { x = 32886, y = 32772, z = 9 }, + { x = 32882, y = 32790, z = 11 }, + { x = 32857, y = 32739, z = 11 }, + { x = 32860, y = 32769, z = 11 }, + { x = 32881, y = 32829, z = 11 }, + { x = 32881, y = 32820, z = 11 }, + { x = 32882, y = 32820, z = 11 }, + }, + }, + [4915] = { + itemId = false, + itemPos = { + { x = 32860, y = 32798, z = 11 }, + { x = 32858, y = 32766, z = 10 }, + { x = 32818, y = 32780, z = 11 }, + { x = 32854, y = 32737, z = 10 }, + { x = 32808, y = 32765, z = 10 }, + }, + }, + [4920] = { + itemId = false, + itemPos = { + { x = 33376, y = 31335, z = 3 }, + { x = 33371, y = 31349, z = 4 }, + { x = 33376, y = 31349, z = 4 }, + { x = 33375, y = 31346, z = 5 }, + { x = 33363, y = 31346, z = 7 }, + { x = 33366, y = 31343, z = 7 }, + { x = 33310, y = 31325, z = 8 }, + { x = 33329, y = 31333, z = 9 }, + }, + }, + [4921] = { + itemId = false, + itemPos = { + { x = 33373, y = 31309, z = 7 }, + { x = 33382, y = 31294, z = 7 }, + { x = 33344, y = 31348, z = 7 }, + { x = 33328, y = 31352, z = 7 }, + { x = 33298, y = 31287, z = 9 }, + { x = 33297, y = 31287, z = 9 }, + { x = 33296, y = 31287, z = 9 }, + { x = 33296, y = 31288, z = 9 }, + { x = 33298, y = 31288, z = 9 }, + { x = 33298, y = 31289, z = 9 }, + { x = 33297, y = 31289, z = 9 }, + }, + }, + [4930] = { + itemId = false, + itemPos = { + { x = 33110, y = 32385, z = 7 }, + { x = 32958, y = 32322, z = 8 }, + { x = 32955, y = 32288, z = 10 }, + { x = 32942, y = 32283, z = 10 }, + { x = 32945, y = 32313, z = 8 }, + { x = 32963, y = 32319, z = 9 }, + { x = 32955, y = 32304, z = 9 }, + { x = 32984, y = 32314, z = 9 }, + { x = 32968, y = 32324, z = 9 }, + { x = 32978, y = 32290, z = 10 }, + { x = 32963, y = 32297, z = 8 }, + { x = 32963, y = 32299, z = 8 }, + { x = 32963, y = 32301, z = 8 }, + { x = 32963, y = 32303, z = 8 }, + { x = 32963, y = 32312, z = 8 }, + }, + }, + [4931] = { + itemId = false, + itemPos = { + { x = 32965, y = 32310, z = 9 }, + { x = 32965, y = 32309, z = 9 }, + { x = 32964, y = 32309, z = 9 }, + { x = 32963, y = 32309, z = 9 }, + { x = 32962, y = 32309, z = 9 }, + { x = 32961, y = 32309, z = 9 }, + { x = 32960, y = 32309, z = 9 }, + { x = 32959, y = 32309, z = 9 }, + { x = 32959, y = 32310, z = 9 }, + { x = 32959, y = 32311, z = 9 }, + { x = 32958, y = 32311, z = 9 }, + { x = 32957, y = 32311, z = 9 }, + { x = 32956, y = 32311, z = 9 }, + { x = 32956, y = 32310, z = 9 }, + { x = 32955, y = 32310, z = 9 }, + { x = 32954, y = 32310, z = 9 }, + { x = 32953, y = 32310, z = 9 }, + { x = 32953, y = 32311, z = 9 }, + { x = 32953, y = 32312, z = 9 }, + { x = 32953, y = 32313, z = 9 }, + { x = 32953, y = 32314, z = 9 }, + { x = 32954, y = 32314, z = 9 }, + { x = 32955, y = 32314, z = 9 }, + { x = 32956, y = 32314, z = 9 }, + { x = 32956, y = 32315, z = 9 }, + { x = 32956, y = 32316, z = 9 }, + { x = 32956, y = 32317, z = 9 }, + { x = 32957, y = 32317, z = 9 }, + { x = 32957, y = 32318, z = 9 }, + { x = 32957, y = 32319, z = 9 }, + { x = 32958, y = 32319, z = 9 }, + { x = 32959, y = 32319, z = 9 }, + { x = 32960, y = 32319, z = 9 }, + { x = 32960, y = 32318, z = 9 }, + { x = 32960, y = 32317, z = 9 }, + { x = 32961, y = 32317, z = 9 }, + { x = 32962, y = 32317, z = 9 }, + { x = 32962, y = 32318, z = 9 }, + { x = 32962, y = 32319, z = 9 }, + { x = 32970, y = 32314, z = 9 }, + { x = 32980, y = 32308, z = 9 }, + { x = 32955, y = 32282, z = 10 }, + { x = 32983, y = 32289, z = 10 }, + { x = 32944, y = 32309, z = 8 }, + }, + }, + [4932] = { + itemId = false, + itemPos = { + { x = 32974, y = 32296, z = 9 }, + { x = 32967, y = 32319, z = 9 }, + { x = 32963, y = 32280, z = 10 }, + { x = 32963, y = 32282, z = 10 }, + { x = 32963, y = 32284, z = 10 }, + { x = 32963, y = 32286, z = 10 }, + }, + }, + [4933] = { + itemId = false, + itemPos = { + { x = 32945, y = 32288, z = 10 }, + { x = 32948, y = 32288, z = 10 }, + { x = 32951, y = 32288, z = 10 }, + }, + }, + [4935] = { + itemId = false, + itemPos = { + { x = 33464, y = 32157, z = 7 }, + { x = 32019, y = 32470, z = 7 }, + { x = 32460, y = 32928, z = 7 }, + { x = 32119, y = 31734, z = 7 }, + }, + }, + [4936] = { + itemId = false, + itemPos = { + { x = 32026, y = 32468, z = 7 }, + { x = 32025, y = 32468, z = 7 }, + { x = 32024, y = 32468, z = 7 }, + { x = 32018, y = 32467, z = 7 }, + { x = 32017, y = 32467, z = 7 }, + { x = 32023, y = 32468, z = 7 }, + { x = 32022, y = 32468, z = 7 }, + { x = 32021, y = 32468, z = 7 }, + { x = 32019, y = 32468, z = 7 }, + { x = 32020, y = 32468, z = 7 }, + { x = 32018, y = 32468, z = 7 }, + }, + }, + [4937] = { + itemId = false, + itemPos = { + { x = 32034, y = 32456, z = 7 }, + { x = 32034, y = 32457, z = 7 }, + }, + }, + [4950] = { + itemId = false, + itemPos = { + { x = 32616, y = 32529, z = 13 }, + { x = 32464, y = 32654, z = 12 }, + { x = 32662, y = 32713, z = 13 }, + { x = 32660, y = 32736, z = 12 }, + { x = 32720, y = 32773, z = 10 }, + { x = 32720, y = 32749, z = 10 }, + { x = 32746, y = 32773, z = 10 }, + { x = 32746, y = 32749, z = 10 }, + { x = 32750, y = 32696, z = 10 }, + { x = 32755, y = 32729, z = 10 }, + { x = 32687, y = 32726, z = 10 }, + { x = 32724, y = 32728, z = 10 }, + }, + }, + [4952] = { + itemId = false, + itemPos = { + { x = 32687, y = 32707, z = 10 }, + { x = 32698, y = 32715, z = 10 }, + { x = 32693, y = 32729, z = 10 }, + { x = 32681, y = 32729, z = 10 }, + { x = 32676, y = 32715, z = 10 }, + }, + }, + -- Cults of Tibia Quest + [5522] = { + itemId = 25687, + itemPos = { + { x = 33279, y = 32169, z = 8 }, + }, + }, + [5523] = { + itemId = 2471, + itemPos = { + { x = 33300, y = 32277, z = 12 }, + }, + }, + [5524] = { + itemId = 2930, + itemPos = { + { x = 32400, y = 31793, z = 8 }, + }, + }, + [5530] = { + itemId = false, + itemPos = { + { x = 32693, y = 31479, z = 8 }, + { x = 32680, y = 31485, z = 8 }, + }, + }, + [5531] = { + itemId = false, + itemPos = { + { x = 32748, y = 31489, z = 8 }, + { x = 32750, y = 31508, z = 8 }, + }, + }, + [5532] = { + itemId = false, + itemPos = { + { x = 32710, y = 31440, z = 8 }, + { x = 32709, y = 31440, z = 8 }, + { x = 32708, y = 31440, z = 8 }, + { x = 32698, y = 31405, z = 8 }, + }, + }, + [5533] = { + itemId = false, + itemPos = { + { x = 32683, y = 31412, z = 8 }, + { x = 32684, y = 31412, z = 8 }, + }, + }, + [5535] = { + itemId = false, + itemPos = { + { x = 32742, y = 31410, z = 8 }, + { x = 32685, y = 31430, z = 8 }, + { x = 32746, y = 31462, z = 8 }, + { x = 32731, y = 31531, z = 9 }, + { x = 32745, y = 31523, z = 9 }, + { x = 32761, y = 31518, z = 9 }, + { x = 32739, y = 31507, z = 9 }, + { x = 32739, y = 31489, z = 9 }, + { x = 32683, y = 31537, z = 9 }, + { x = 32720, y = 31545, z = 8 }, + }, + }, + [5536] = { + itemId = false, + itemPos = { + { x = 32740, y = 31494, z = 9 }, + { x = 32741, y = 31494, z = 9 }, + }, + }, + [5540] = { + itemId = 25761, + itemPos = { + { x = 33135, y = 31859, z = 10 }, + { x = 33136, y = 31859, z = 10 }, + { x = 33128, y = 31885, z = 11 }, + { x = 33129, y = 31885, z = 11 }, + { x = 33175, y = 31923, z = 12 }, + { x = 33176, y = 31923, z = 12 }, + { x = 33177, y = 31923, z = 12 }, + }, + }, + [5581] = { + itemId = 25726, + itemPos = { + { x = 32350, y = 31657, z = 8 }, + { x = 32351, y = 31657, z = 8 }, + { x = 32352, y = 31657, z = 8 }, + { x = 32353, y = 31657, z = 8 }, + { x = 32327, y = 31692, z = 9 }, + { x = 32328, y = 31692, z = 9 }, + { x = 32329, y = 31692, z = 9 }, + { x = 32528, y = 32468, z = 10 }, + { x = 32529, y = 32468, z = 10 }, + { x = 32530, y = 32468, z = 10 }, + { x = 32531, y = 32468, z = 10 }, + { x = 32532, y = 32468, z = 10 }, + { x = 32533, y = 32468, z = 10 }, + { x = 32534, y = 32468, z = 10 }, + { x = 32535, y = 32468, z = 10 }, + { x = 32536, y = 32468, z = 10 }, + { x = 32537, y = 32468, z = 10 }, + { x = 32538, y = 32468, z = 10 }, + { x = 32539, y = 32468, z = 10 }, + }, + }, -- In Service of Yalahar Quest [7812] = { itemId = 7804, @@ -885,6 +1248,19 @@ ItemAction = { { x = 33324, y = 31372, z = 14 }, }, }, + -- Forgotten Knowledge Quest + [24875] = { + itemId = 23730, + itemPos = { x = 32860, y = 31644, z = 10 }, + }, + [24876] = { + itemId = 1503, + itemPos = { x = 32891, y = 31619, z = 10 }, + }, + [24877] = { + itemId = 1503, + itemPos = { x = 32924, y = 31636, z = 14 }, + }, -- The Cursed Crystal [25018] = { itemId = false, @@ -1591,6 +1967,152 @@ ItemAction = { { x = 32242, y = 32611, z = 11 }, }, }, + -- Dangerous Depths Quest + [57231] = { + itemId = 7062, + itemPos = { + { x = 33773, y = 32249, z = 14 }, + { x = 33774, y = 32249, z = 14 }, + }, + }, + [57240] = { + itemId = false, + itemPos = { + { x = 33979, y = 32209, z = 14 }, + { x = 33979, y = 32208, z = 14 }, + { x = 33933, y = 32163, z = 14 }, + { x = 33925, y = 32217, z = 14 }, + { x = 33979, y = 32207, z = 14 }, + { x = 33979, y = 32206, z = 14 }, + { x = 33925, y = 32215, z = 14 }, + { x = 33925, y = 32216, z = 14 }, + { x = 33924, y = 32217, z = 14 }, + { x = 33924, y = 32218, z = 14 }, + { x = 33932, y = 32162, z = 14 }, + { x = 33933, y = 32162, z = 14 }, + }, + }, + [57241] = { + itemId = false, + itemPos = { + { x = 33990, y = 32195, z = 14 }, + { x = 33983, y = 32207, z = 14 }, + { x = 33983, y = 32206, z = 14 }, + { x = 33983, y = 32208, z = 14 }, + { x = 33992, y = 32195, z = 14 }, + { x = 33983, y = 32209, z = 14 }, + { x = 33991, y = 32195, z = 14 }, + }, + }, + [57242] = { + itemId = false, + itemPos = { + { x = 33863, y = 32177, z = 14 }, + { x = 33863, y = 32178, z = 14 }, + { x = 33863, y = 32179, z = 14 }, + { x = 33863, y = 32181, z = 14 }, + { x = 33863, y = 32182, z = 14 }, + { x = 33863, y = 32180, z = 14 }, + { x = 33863, y = 32175, z = 14 }, + { x = 33863, y = 32176, z = 14 }, + }, + }, + [57300] = { + itemId = false, + itemPos = { + { x = 34033, y = 32000, z = 14 }, + { x = 33982, y = 31982, z = 14 }, + { x = 34002, y = 31986, z = 14 }, + }, + }, + [57301] = { + itemId = false, + itemPos = { + { x = 33993, y = 32264, z = 14 }, + { x = 33947, y = 32258, z = 14 }, + { x = 34027, y = 32245, z = 14 }, + }, + }, + [57302] = { + itemId = false, + itemPos = { + { x = 33927, y = 32338, z = 14 }, + { x = 33898, y = 32338, z = 14 }, + { x = 33958, y = 32338, z = 14 }, + }, + }, + [57350] = { + itemId = 27505, + itemPos = { x = 33214, y = 32280, z = 15 }, + }, + [57351] = { + itemId = 27503, + itemPos = { x = 33358, y = 32267, z = 15 }, + }, + [57352] = { + itemId = 27503, + itemPos = { x = 33275, y = 32310, z = 15 }, + }, + [57353] = { + itemId = 27505, + itemPos = { x = 33302, y = 32353, z = 15 }, + }, + [57354] = { + itemId = 27507, + itemPos = { x = 33330, y = 32290, z = 15 }, + }, + [57355] = { + itemId = 27507, + itemPos = { x = 33224, y = 32361, z = 15 }, + }, + [57356] = { + itemId = 27503, + itemPos = { x = 33212, y = 32147, z = 15 }, + }, + [57357] = { + itemId = 27505, + itemPos = { x = 33300, y = 32134, z = 15 }, + }, + [57358] = { + itemId = 27503, + itemPos = { x = 33277, y = 32172, z = 15 }, + }, + [57359] = { + itemId = 27505, + itemPos = { x = 33246, y = 32162, z = 15 }, + }, + [57360] = { + itemId = 27507, + itemPos = { x = 33222, y = 32182, z = 15 }, + }, + [57361] = { + itemId = 27507, + itemPos = { x = 33338, y = 32164, z = 15 }, + }, + [57362] = { + itemId = 27503, + itemPos = { x = 33428, y = 32181, z = 15 }, + }, + [57363] = { + itemId = 27505, + itemPos = { x = 33539, y = 32213, z = 15 }, + }, + [57364] = { + itemId = 27503, + itemPos = { x = 33501, y = 32255, z = 15 }, + }, + [57365] = { + itemId = 27505, + itemPos = { x = 33493, y = 32216, z = 15 }, + }, + [57366] = { + itemId = 27507, + itemPos = { x = 33490, y = 32180, z = 15 }, + }, + [57367] = { + itemId = 27507, + itemPos = { x = 33454, y = 32215, z = 15 }, + }, -- The Ice Islands Quest, Nibelor 1: Breaking the Ice [60000] = { itemId = 7185, @@ -1623,6 +2145,11 @@ ItemUnique = { itemId = 2576, itemPos = { x = 32455, y = 31166, z = 12 }, }, + -- The First Dragon + [1066] = { + itemId = 3657, + itemPos = { x = 33608, y = 31022, z = 14 }, + }, -- The Pits of Inferno Quest [2000] = { itemId = 599, @@ -2649,4 +3176,17 @@ ItemUnique = { itemId = 1949, itemPos = { x = 32826, y = 32347, z = 9 }, }, + -- Dangerous Depths Quest + [57234] = { + itemId = 2472, + itemPos = { x = 33841, y = 32124, z = 14 }, + }, + [57235] = { + itemId = 21301, + itemPos = { x = 33755, y = 32163, z = 14 }, + }, + [57236] = { + itemId = 9253, + itemPos = { x = 33755, y = 32161, z = 14 }, + }, } diff --git a/data-otservbr-global/startup/tables/lever.lua b/data-otservbr-global/startup/tables/lever.lua index 86798188a0a..ab887209866 100644 --- a/data-otservbr-global/startup/tables/lever.lua +++ b/data-otservbr-global/startup/tables/lever.lua @@ -15,6 +15,33 @@ LeverAction = { { x = 32972, y = 32412, z = 11 }, }, }, + -- The Secret Library Quest + [4906] = { + itemId = false, + itemPos = { + { x = 33251, y = 32039, z = 8 }, + { x = 33218, y = 32096, z = 10 }, + }, + }, + -- Cults of Tibia Quest + [5500] = { + itemId = 8911, + itemPos = { + { x = 33095, y = 31942, z = 15 }, + }, + }, + [5501] = { + itemId = 8911, + itemPos = { + { x = 33138, y = 31952, z = 15 }, + }, + }, + [5520] = { + itemId = 9110, + itemPos = { + { x = 33299, y = 32144, z = 10 }, + }, + }, -- The Pits of Inferno Quest [7799] = { itemId = 431, @@ -102,6 +129,19 @@ LeverAction = { { x = 32576, y = 31862, z = 14 }, }, }, + -- Forgotten Knowledge Quest + [26663] = { + itemId = 9125, + itemPos = { + { x = 32792, y = 32820, z = 13 }, + }, + }, + [26664] = { + itemId = 9125, + itemPos = { + { x = 32840, y = 32820, z = 13 }, + }, + }, -- Dawnport bridge lever -- Path: data\scripts\actions\dawnport\lever.lua [30001] = { @@ -230,9 +270,12 @@ LeverAction = { -- The Pits of Inferno Quest [50160] = { itemId = 2772, - itemPos = { - { x = 32853, y = 32318, z = 9 }, - }, + itemPos = { x = 32853, y = 32318, z = 9 }, + }, + -- The Pits of Inferno Quest + [57234] = { + itemId = 2772, + itemPos = { x = 33841, y = 32080, z = 14 }, }, } @@ -260,10 +303,6 @@ LeverUnique = { itemPos = { x = 33172, y = 31896, z = 8 }, }, -- Ferumbras' Ascension Quest - [1021] = { - itemId = 8911, - itemPos = { x = 33270, y = 31476, z = 14 }, - }, [1022] = { itemId = 8911, itemPos = { x = 33229, y = 31499, z = 13 }, @@ -492,12 +531,6 @@ LeverUnique = { itemId = 2773, itemPos = { x = 33582, y = 31844, z = 10 }, }, - -- The first dragon quest lever - -- Path: data\scripts\actions\quests\first_dragon\lever.lua - [30003] = { - itemId = 8911, - itemPos = { x = 33583, y = 30992, z = 14 }, - }, -- Thais lighthouse quest -- Path: data\scripts\quests\thais_lighthouse\action-lever.lua [30004] = { diff --git a/data-otservbr-global/startup/tables/teleport.lua b/data-otservbr-global/startup/tables/teleport.lua index 367dc51ba4e..94a7d57e822 100644 --- a/data-otservbr-global/startup/tables/teleport.lua +++ b/data-otservbr-global/startup/tables/teleport.lua @@ -9,6 +9,38 @@ TeleportAction = { { x = 32210, y = 32292, z = 6 }, }, }, + -- The Secret Library Quest + [4905] = { + itemId = 25054, + itemPos = { + { x = 33246, y = 32107, z = 8 }, + { x = 33246, y = 32098, z = 8 }, + }, + }, + [4906] = { + itemId = 1949, + itemPos = { + { x = 33288, y = 32106, z = 9 }, + { x = 33288, y = 32107, z = 9 }, + { x = 33287, y = 32106, z = 9 }, + { x = 33287, y = 32107, z = 9 }, + { x = 33286, y = 32106, z = 9 }, + { x = 33286, y = 32107, z = 9 }, + }, + }, + -- Cults of Tibia Quest + [5517] = { + itemId = 1949, + itemPos = { + { x = 33459, y = 32267, z = 10 }, + }, + }, + [5518] = { + itemId = 1949, + itemPos = { + { x = 33449, y = 32241, z = 7 }, + }, + }, -- Barbarian Test - Temple Citizen Svargrond [30032] = { itemId = 1949, @@ -24,9 +56,39 @@ TeleportAction = { { x = 32177, y = 31869, z = 15 }, }, }, + -- Dangerous Depths Quest + [57230] = { + itemId = 1949, + itemPos = { + { x = 33827, y = 32172, z = 14 }, + { x = 33829, y = 32128, z = 14 }, + { x = 33777, y = 32192, z = 14 }, + }, + }, } TeleportUnique = { + -- Forgotten Knowledge Quest + [1067] = { + itemId = 1949, + itemPos = { x = 32915, y = 31637, z = 14 }, + }, + [1068] = { + itemId = 1949, + itemPos = { x = 32676, y = 32888, z = 14 }, + }, + [1070] = { + itemId = 1949, + itemPos = { x = 32316, y = 31093, z = 14 }, + }, + [1071] = { + itemId = 1949, + itemPos = { x = 32849, y = 32689, z = 15 }, + }, + [1072] = { + itemId = 1949, + itemPos = { x = 32033, y = 32859, z = 14 }, + }, -- Issavi town teleport [9515] = { itemId = 1949, @@ -34,6 +96,11 @@ TeleportUnique = { }, -- The first dragon quest -- Path: data\scripts\movements\quests\first_dragon\entrance_teleport.lua + -- Boss First Dragon + [24889] = { + itemId = 1949, + itemPos = { x = 33597, y = 30996, z = 14 }, + }, -- Tazhadur entrance [35001] = { itemId = 8649, diff --git a/data-otservbr-global/startup/tables/teleport_item.lua b/data-otservbr-global/startup/tables/teleport_item.lua index c9595228a49..c09dd9e22fa 100644 --- a/data-otservbr-global/startup/tables/teleport_item.lua +++ b/data-otservbr-global/startup/tables/teleport_item.lua @@ -49,19 +49,97 @@ TeleportItemAction = { { x = 32172, y = 32439, z = 7 }, }, }, - -- Teleports Thais + -- Forgotten Knowledge Quest - Teleports Thais [24873] = { - itemId = false, + itemId = 25047, itemPos = { { x = 32325, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 25051, + itemPos = { { x = 32328, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 25049, + itemPos = { { x = 32331, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 25053, + itemPos = { { x = 32334, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 25057, + itemPos = { { x = 32337, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 25055, + itemPos = { { x = 32340, y = 32087, z = 7 }, + }, + }, + [24873] = { + itemId = 10840, + itemPos = { { x = 32332, y = 32094, z = 7 }, }, }, + [24873] = { + itemId = 25048, + itemPos = { + { x = 32805, y = 31657, z = 8 }, + }, + }, + [24873] = { + itemId = 25052, + itemPos = { + { x = 32786, y = 32818, z = 13 }, + }, + }, + [24873] = { + itemId = 25050, + itemPos = { + { x = 32637, y = 32255, z = 7 }, + }, + }, + [24873] = { + itemId = 25054, + itemPos = { + { x = 33341, y = 31167, z = 7 }, + }, + }, + [24873] = { + itemId = 25058, + itemPos = { + { x = 32205, y = 31036, z = 10 }, + }, + }, + [24873] = { + itemId = 25056, + itemPos = { + { x = 32780, y = 32684, z = 14 }, + }, + }, + [24873] = { + itemId = 10842, + itemPos = { + { x = 32906, y = 32846, z = 13 }, + }, + }, + [26668] = { + itemId = 1949, + itemPos = { + { x = 33396, y = 31129, z = 9 }, + }, + }, } TeleportItemUnique = { diff --git a/data-otservbr-global/startup/tables/tile.lua b/data-otservbr-global/startup/tables/tile.lua index 546bc66ef65..59d9d3be69f 100644 --- a/data-otservbr-global/startup/tables/tile.lua +++ b/data-otservbr-global/startup/tables/tile.lua @@ -54,6 +54,7 @@ TileAction = { { x = 32696, y = 31720, z = 7 }, { x = 32697, y = 31720, z = 7 }, { x = 32698, y = 31720, z = 7 }, + { x = 32691, y = 31724, z = 7 }, }, }, --Dawnport diff --git a/data-otservbr-global/startup/tables/writeable.lua b/data-otservbr-global/startup/tables/writeable.lua index 226fe46c3b7..538fccdf72a 100644 --- a/data-otservbr-global/startup/tables/writeable.lua +++ b/data-otservbr-global/startup/tables/writeable.lua @@ -132,7 +132,6 @@ Nobody knows where the elder gods came from, or whether they had always existed Uman Zathroth regarded Fardos's undertakings thoughtfully. Uman was sagacious and held awesome magical powers. Most importantly, however, he was driven by an insatiable hunger for knowledge and enlightenment. In his essence he resembled Fardos, but where Fardos worked openly and logically, Uman's domain was the realm of mystery. Still, he shared Fardos's interest in creation, whereas his dark half Zathroth was essentially corruptive. Zathroth was a vain god who was painfully aware that his own creative powers were poor. Because of this he looked at Fardos's work of creation with jealousy, and from the very beginning he was determined to prevent or at least corrupt it in any way he could. Fardos, who did not suspect this, asked him for assistance because he had accepted the fact that he could not achieve creation on his own, but of course Zathroth denied. Uman, however, agreed to help. And from that he and Fardos worked together on the great project that was creation. - Unfortunately, their combined efforts were hardly more successful. Just like before, everything Fardos and Uman created was swallowed by the void as soon as it came into existence, and the two gods sadly saw their creation run through their fingers like water through a sieve. On the other hand, Zathroth, who had been watching their efforts with suspicion, rejoiced. He ridiculed their efforts. However, his glee changed into surprise and anger when he found that something strange happened, something which perhaps Uman and Fardos did not expect themselves. To this day, nobody knows precisely what it was that caused it. Perhaps the power that had been spent lured another entity out of the void, or it might be that it simply awoke another divine entity from its slumber. Some even claim that in some mysterious way the power that had been spent by Uman and Fardos actually created a new entity. Whatever the truth may be, a new goddess stepped out of the void like a new-born mermaid from her shell. The amazed elder gods watched her divine beauty in awed admiration, for everything in her was perfect harmony. They agreed to call her Tibiasula. Zathroth, however, stood by and fumed with silent hate. But cunning as he was, he hid his resentment well and feigned to share the joy of the other elder gods. ]], }, @@ -147,7 +146,6 @@ Zathroth watched the progress of creation with wrath and disgust. If he had had As he grew up, Brog was pained by the fire burning inside him, until one day when it grew unbearable he summoned all his magical powers and released as much of the painful flame into the world as he could. The searing fire mixed with his rage, and from it rose Garsharak, the very first dragon, who later sired a whole race of intelligent, giant lizards, a race that would eventually bring terror and chaos into Tibia. Brog watched the terrible creature he had created rather accidentally, and he rejoiced when he saw just how fierce and powerful it was. Though he was rather stupid he, too, had the gift to create life, which in an act of vanity he next used to create the cyclopes in his own image. - Zathroth watched Brog's experiments with great interest. So far he had not held his son in high esteem, but here was something for which he himself admittedly had little talent for. Since he did not understand the laws of life himself he knew that Brog's gift could prove to be a great asset. He called his son to him and told him to go on with his experiments, urging him to create something more terrifying and destructive than cyclopes. Even though these giants were ferocious and strong, they were not quite as destructive as he wanted them to be. In fact, due to their love of mining and smithing the cyclopes were a creative rather than a destructive race. Worse, they were not propagating fast enough to make them a real threat to creation. For this reason Brog went on to create trolls and goblins, races that were weaker than the cyclopes, but propagated much faster. However, his undisputed masterpiece were the orcs, a race of fearsome, single-minded warriors who lived only to expand and conquer. Soon they had spread all over Tibia, and they were the scourge of all that was alive. ]], }, @@ -723,7 +721,6 @@ Thoughts and Notations on the Noble Craft of Potion-Making, by Grandsieur Haruva The Gods gave their gifts freely, but bestowed them not on all creatures alike. Some ancient creatures were possessed of a far-reaching will to conquer and subdue all others through their thoughts alone, while the newer beings could weave magic in defense or had strength and swiftness to defend and escape the wiles laid out to ensnare them. Some animals and plants, simple though they may seem to us, yet are deadly poisonous in order to ward off their hunter. - But only the more intelligent beings - and of those, only a select few - possess the art of making powerful concoctions that enhance their faculties. The humble woodman or wanderer will never be able to fulfil the complex rites, or even grasp the concept, of the trimagical umbralistic principle of the equinox formula that is crucial to the craft of magical potions. But still, they can drink, and appreciate, the brews we make to keep a warrior's body alive in a fight, the mage's mana when drained, the paladin's spirit when they need to gather holy force. ... (you lose interest and close the book) @@ -742,7 +739,6 @@ The cyclops ... ... hid the ancient amulet beneath the sand, before ...should have listened to ... Must hide... paper, hope an adventurer will... - ... amulet will be washed ashore if not found... To any adventurer friend: ... shovel... beach... .. dig there. ... take it to Morris, maybe he ... decipher the engravings. diff --git a/data-otservbr-global/world/otservbr-monster.xml b/data-otservbr-global/world/otservbr-monster.xml index 80c5f5d4ff3..424e4210b80 100644 --- a/data-otservbr-global/world/otservbr-monster.xml +++ b/data-otservbr-global/world/otservbr-monster.xml @@ -1780,6 +1780,9 @@ + + + @@ -2116,6 +2119,9 @@ + + + @@ -3314,12 +3320,15 @@ - - + + + + + @@ -9595,6 +9604,7 @@ + @@ -14604,6 +14614,9 @@ + + + @@ -51892,8 +51905,9 @@ - - + + + diff --git a/data-otservbr-global/world/otservbr-npc.xml b/data-otservbr-global/world/otservbr-npc.xml index 5a475b8999d..5c53601aa9c 100644 --- a/data-otservbr-global/world/otservbr-npc.xml +++ b/data-otservbr-global/world/otservbr-npc.xml @@ -2818,6 +2818,9 @@ + + + diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua index eee28b632d6..c526553132d 100644 --- a/data/events/scripts/player.lua +++ b/data/events/scripts/player.lua @@ -315,7 +315,8 @@ function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, end -- Reward System - if toPosition.x == CONTAINER_POSITION then + local containerThing = tile and tile:getItemByType(ITEM_TYPE_CONTAINER) + if containerThing and toPosition.x == CONTAINER_POSITION then local containerId = toPosition.y - 64 local container = self:getContainerById(containerId) if not container then @@ -371,9 +372,17 @@ end function Player:onItemMoved(item, count, fromPosition, toPosition, fromCylinder, toCylinder) if IsRunningGlobalDatapack() then + -- The Secret Library Quest + if toPosition == Position(32460, 32928, 7) and item.itemid == 3578 then + toPosition:sendMagicEffect(CONST_ME_HEARTS) + self:say("You feed the turtle, now you may pass.", TALKTYPE_MONSTER_SAY) + Game.setStorageValue(Storage.Quest.U11_80.TheSecretLibrary.SmallIslands.Turtle, os.time() + 10 * 60) + item:remove(1) + end + -- Cults of Tibia begin - local frompos = Position(33023, 31904, 14) -- Checagem - local topos = Position(33052, 31932, 15) -- Checagem + local frompos = Position(33023, 31904, 14) + local topos = Position(33052, 31932, 15) local removeItem = false if self:getPosition():isInRange(frompos, topos) and item:getId() == 23729 then local tile = Tile(toPosition) @@ -527,20 +536,17 @@ function Player:onGainExperience(target, exp, rawExp) self:addCondition(soulCondition) end - -- XP Boost Bonus - useStaminaXpBoost(self) -- Use stamina XP boost (store or daily reward) + -- Apply XP Boost (Store or Daily Reward) + useStaminaXpBoost(self) local xpBoostTimeLeft = self:getXpBoostTime() - local stillHasXpBoost = xpBoostTimeLeft > 0 - local xpBoostPercent = stillHasXpBoost and self:getXpBoostPercent() or 0 - - self:setXpBoostPercent(xpBoostPercent) + local hasXpBoost = xpBoostTimeLeft > 0 + local xpBoostPercent = hasXpBoost and self:getXpBoostPercent() or 0 -- Stamina Bonus local staminaBonusXp = 1 - local isStaminaEnabled = configManager.getBoolean(configKeys.STAMINA_SYSTEM) - useStamina(self, isStaminaEnabled) - if isStaminaEnabled then + if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then + useStamina(self, true) staminaBonusXp = self:getFinalBonusStamina() self:setStaminaXpBoost(staminaBonusXp * 100) end @@ -548,12 +554,12 @@ function Player:onGainExperience(target, exp, rawExp) -- Concoction System useConcoctionTime(self) - -- Boosted creature - if target:getName():lower() == (Game.getBoostedCreature()):lower() then + -- Apply Boosted Creature Bonus + if target:getName():lower() == Game.getBoostedCreature():lower() then exp = exp * 2 end - -- Prey system + -- Prey System if configManager.getBoolean(configKeys.PREY_ENABLED) then local monsterType = target:getType() if monsterType and monsterType:raceId() > 0 then @@ -561,18 +567,20 @@ function Player:onGainExperience(target, exp, rawExp) end end + -- VIP Bonus Experience if configManager.getBoolean(configKeys.VIP_SYSTEM_ENABLED) then local vipBonusExp = configManager.getNumber(configKeys.VIP_BONUS_EXP) if vipBonusExp > 0 and self:isVip() then - vipBonusExp = (vipBonusExp > 100 and 100) or vipBonusExp - exp = exp * (1 + (vipBonusExp / 100)) + exp = exp * (1 + math.min(vipBonusExp, 100) / 100) end end - local lowLevelBonuxExp = self:getFinalLowLevelBonus() - local baseRate = self:getFinalBaseRateExperience() + -- Final Adjustments: Low Level Bonus and Base Rate + local lowLevelBonusExp = self:getFinalLowLevelBonus() + local baseRateExp = self:getFinalBaseRateExperience() - return (exp + (exp * (xpBoostPercent / 100) + (exp * (lowLevelBonuxExp / 100)))) * staminaBonusXp * baseRate + -- Return final experience value + return (exp * (1 + xpBoostPercent / 100 + lowLevelBonusExp / 100)) * staminaBonusXp * baseRateExp end function Player:onLoseExperience(exp) @@ -584,42 +592,35 @@ function Player:onGainSkillTries(skill, tries) if IsRunningGlobalDatapack() and isSkillGrowthLimited(self, skill) then return 0 end + if not APPLY_SKILL_MULTIPLIER then return tries end - -- Event scheduler skill rate - local STAGES_DEFAULT = nil - if configManager.getBoolean(configKeys.RATE_USE_STAGES) then - STAGES_DEFAULT = skillsStages - end - local SKILL_DEFAULT = self:getSkillLevel(skill) - local RATE_DEFAULT = configManager.getNumber(configKeys.RATE_SKILL) + -- Default skill rate settings + local rateSkillStages = configManager.getBoolean(configKeys.RATE_USE_STAGES) and skillsStages or nil + local currentSkillLevel = self:getSkillLevel(skill) + local baseRate = configManager.getNumber(configKeys.RATE_SKILL) + -- Special case for magic level if skill == SKILL_MAGLEVEL then - -- Magic Level - if configManager.getBoolean(configKeys.RATE_USE_STAGES) then - STAGES_DEFAULT = magicLevelStages - end - SKILL_DEFAULT = self:getBaseMagicLevel() - RATE_DEFAULT = configManager.getNumber(configKeys.RATE_MAGIC) + rateSkillStages = configManager.getBoolean(configKeys.RATE_USE_STAGES) and magicLevelStages or nil + currentSkillLevel = self:getBaseMagicLevel() + baseRate = configManager.getNumber(configKeys.RATE_MAGIC) end - local skillOrMagicRate = getRateFromTable(STAGES_DEFAULT, SKILL_DEFAULT, RATE_DEFAULT) + -- Calculate skill rate from stages and schedule + local skillRate = getRateFromTable(rateSkillStages, currentSkillLevel, baseRate) + skillRate = (SCHEDULE_SKILL_RATE ~= 100) and (skillRate * SCHEDULE_SKILL_RATE / 100) or skillRate - if SCHEDULE_SKILL_RATE ~= 100 then - skillOrMagicRate = math.max(0, (skillOrMagicRate * SCHEDULE_SKILL_RATE) / 100) + -- Apply VIP boost if applicable + if configManager.getBoolean(configKeys.VIP_SYSTEM_ENABLED) and self:isVip() then + local vipBonusSkill = math.min(configManager.getNumber(configKeys.VIP_BONUS_SKILL), 100) + skillRate = skillRate + (skillRate * (vipBonusSkill / 100)) end - if configManager.getBoolean(configKeys.VIP_SYSTEM_ENABLED) then - local vipBoost = configManager.getNumber(configKeys.VIP_BONUS_SKILL) - if vipBoost > 0 and self:isVip() then - vipBoost = (vipBoost > 100 and 100) or vipBoost - skillOrMagicRate = skillOrMagicRate + (skillOrMagicRate * (vipBoost / 100)) - end - end - - return tries / 100 * (skillOrMagicRate * 100) + -- Calculate and return the final experience gain + return tries * skillRate end function Player:onCombat(target, item, primaryDamage, primaryType, secondaryDamage, secondaryType) @@ -670,24 +671,3 @@ function Player:onChangeZone(zone) end function Player:onInventoryUpdate(item, slot, equip) end - -function Player:getURL() - local playerLink = string.gsub(self:getName(), "%s+", "+") - local serverURL = configManager.getString(configKeys.URL) - return serverURL .. "/characters/" .. playerLink -end - -function Player:getMarkdownLink() - local vocation = self:vocationAbbrev() - local emoji = ":school_satchel:" - if self:isKnight() then - emoji = ":crossed_swords:" - elseif self:isPaladin() then - emoji = ":bow_and_arrow:" - elseif self:isDruid() then - emoji = ":herb:" - elseif self:isSorcerer() then - emoji = ":crystal_ball:" - end - return "**[" .. self:getName() .. "](" .. self:getURL() .. ")** " .. emoji .. " [_" .. vocation .. "_]" -end diff --git a/data/items/items.xml b/data/items/items.xml index 79f122afb9a..c1b8e8a63ba 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -4435,6 +4435,9 @@ + + + @@ -51874,6 +51877,10 @@ hands of its owner. Granted by TibiaRoyal.com"/> + + + + @@ -53150,6 +53157,7 @@ hands of its owner. Granted by TibiaRoyal.com"/> + @@ -53200,7 +53208,10 @@ hands of its owner. Granted by TibiaRoyal.com"/> - + + + + @@ -53994,7 +54005,7 @@ hands of its owner. Granted by TibiaRoyal.com"/> - + @@ -75131,7 +75142,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75157,9 +75170,11 @@ Granted by TibiaGoals.com"/> - + + + - + @@ -75186,7 +75201,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75212,7 +75229,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75238,7 +75257,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75264,7 +75285,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75292,7 +75315,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75319,7 +75344,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75346,7 +75373,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75373,7 +75402,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75400,7 +75431,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75427,7 +75460,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75480,7 +75515,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75510,7 +75547,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75540,7 +75579,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75570,7 +75611,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75619,8 +75662,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75652,8 +75699,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75714,8 +75765,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75747,8 +75802,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75945,7 +76004,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76108,7 +76169,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76152,7 +76215,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76167,8 +76232,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -76361,5 +76430,3305 @@ Granted by TibiaGoals.com"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/libs/compat/compat.lua b/data/libs/compat/compat.lua index 061d1dbe47e..ed1a229a826 100644 --- a/data/libs/compat/compat.lua +++ b/data/libs/compat/compat.lua @@ -572,8 +572,8 @@ function isPremium(cid) return p ~= nil and p:isPremium() or false end -function getBlessingsCost(level, byCommand) - return Blessings.getBlessingsCost(level, byCommand) +function getBlessingCost(level, byCommand, blessId) + return Blessings.getBlessingCost(level, byCommand, blessId) end function getPvpBlessingCost(level, byCommand) @@ -618,18 +618,7 @@ function getPlayerGUIDByName(name) end function getAccountNumberByPlayerName(name) - local player = Player(name) - if player then - return player:getAccountId() - end - - local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(name)) - if resultId ~= false then - local accountId = Result.getNumber(resultId, "account_id") - Result.free(resultId) - return accountId - end - return 0 + return Game.getPlayerAccountId(name) end getPlayerAccountBalance = getPlayerBalance diff --git a/data/libs/functions/boss_lever.lua b/data/libs/functions/boss_lever.lua index b1141619ce2..ae8a89d0e54 100644 --- a/data/libs/functions/boss_lever.lua +++ b/data/libs/functions/boss_lever.lua @@ -4,6 +4,7 @@ ---@field private createBoss function ---@field private timeToFightAgain number ---@field private timeToDefeat number +---@field private minPlayers number ---@field private timeAfterKill number ---@field private requiredLevel number ---@field private disabled boolean @@ -29,6 +30,7 @@ local config = { } requiredLevel = 250, timeToFightAgain = 10 * 60 * 60, -- In seconds + minPlayers = 4, playerPositions = { { pos = Position(33638, 32562, 13), teleport = Position(33617, 32567, 13) }, { pos = Position(33639, 32562, 13), teleport = Position(33617, 32567, 13) }, @@ -40,7 +42,7 @@ local config = { from = Position(33607, 32553, 13), to = Position(33627, 32570, 13) }, - onUseExtra = function(player) + onUseExtra = function(player, infoPositions) player:teleportTo(Position(33618, 32523, 15)) player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) end, @@ -56,7 +58,7 @@ setmetatable(BossLever, { error("BossLever: boss is required") end return setmetatable({ - name = boss.name, + name = boss.name:lower(), encounter = config.encounter, bossPosition = boss.position, timeToFightAgain = config.timeToFightAgain or configManager.getNumber(configKeys.BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN), @@ -65,6 +67,7 @@ setmetatable(BossLever, { requiredLevel = config.requiredLevel or 0, createBoss = boss.createFunction, disabled = config.disabled, + minPlayers = config.minPlayers or 1, playerPositions = config.playerPositions, onUseExtra = config.onUseExtra or function() end, exitTeleporter = config.exitTeleporter, @@ -174,7 +177,7 @@ function BossLever:onUse(player) return true end - local isAccountNormal = creature:getAccountType() == ACCOUNT_TYPE_NORMAL + local isAccountNormal = creature:getAccountType() < ACCOUNT_TYPE_GAMEMASTER if isAccountNormal and creature:getLevel() < self.requiredLevel then local message = "All players need to be level " .. self.requiredLevel .. " or higher." creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) @@ -182,8 +185,8 @@ function BossLever:onUse(player) return false end + local infoPositions = lever:getInfoPositions() if creature:getGroup():getId() < GROUP_TYPE_GOD and isAccountNormal and self:lastEncounterTime(creature) > os.time() then - local infoPositions = lever:getInfoPositions() for _, posInfo in pairs(infoPositions) do local currentPlayer = posInfo.creature if currentPlayer then @@ -206,11 +209,18 @@ function BossLever:onUse(player) return false end - self.onUseExtra(creature) - return true + return self.onUseExtra(creature, infoPositions) ~= false end) lever:checkPositions() + if #lever:getPlayers() < self.minPlayers then + lever:executeOnPlayers(function(creature) + local message = string.format("You need %d qualified players for this challenge.", self.minPlayers) + creature:sendTextMessage(MESSAGE_EVENT_ADVANCE, message) + creature:getPosition():sendMagicEffect(CONST_ME_POFF) + end) + return false + end if lever:checkConditions() then zone:removeMonsters() for _, monster in pairs(self.monsters) do diff --git a/data/libs/functions/functions.lua b/data/libs/functions/functions.lua index 2327a1cf937..4b9a94968ca 100644 --- a/data/libs/functions/functions.lua +++ b/data/libs/functions/functions.lua @@ -110,21 +110,6 @@ function getRateFromTable(t, level, default) return default end -function getAccountNumberByPlayerName(name) - local player = Player(name) - if player ~= nil then - return player:getAccountId() - end - - local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(name)) - if resultId ~= false then - local accountId = Result.getNumber(resultId, "account_id") - Result.free(resultId) - return accountId - end - return 0 -end - function getMoneyCount(string) local b, e = string:find("%d+") local money = b and e and tonumber(string:sub(b, e)) or -1 diff --git a/data/libs/functions/game.lua b/data/libs/functions/game.lua index a7c7f7617ce..ae13f50038a 100644 --- a/data/libs/functions/game.lua +++ b/data/libs/functions/game.lua @@ -167,3 +167,18 @@ function Game.getTimeInWords(seconds) end return timeStr end + +function Game.getPlayerAccountId(name) + local player = Player(name) + if player then + return player:getAccountId() + end + + local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(name)) + if resultId then + local accountId = result.getNumber(resultId, "account_id") + result.free(resultId) + return accountId + end + return 0 +end diff --git a/data/libs/functions/lever.lua b/data/libs/functions/lever.lua index 54e6e5c4915..39802af49d2 100644 --- a/data/libs/functions/lever.lua +++ b/data/libs/functions/lever.lua @@ -5,6 +5,7 @@ setmetatable(Lever, { local lever_data = { positions = {}, info_positions = nil, + players = {}, condition = function() return true end, @@ -51,6 +52,19 @@ function Lever.getInfoPositions(self) return self.info_positions end +---@return table +function Lever.getPlayers(self) + return self.players +end + +---@param player Player +---@return nil +function Lever.addPlayer(self, player) + if player and player:isPlayer() then + table.insert(self.players, player) + end +end + --[[ lever:setCondition(function(creature)) @@ -109,6 +123,7 @@ function Lever:checkPositions() local ground = tile:getGround() local actionID = ground:getActionId() local uniqueID = ground:getUniqueId() + self:addPlayer(creature) table.insert(array, { tile = tile, creature = creature, @@ -140,6 +155,12 @@ function Lever.checkConditions(self) -- It will check the conditions defined in return true end +function Lever.executeOnPlayers(self, func) + for _, player in pairs(self:getPlayers()) do + func(player) + end +end + ---@return nil function Lever.teleportPlayers(self) -- It will teleport all players to the positions defined in setPositions() local info = self:getInfoPositions() diff --git a/data/libs/functions/player.lua b/data/libs/functions/player.lua index a8497b9bef1..0350310e397 100644 --- a/data/libs/functions/player.lua +++ b/data/libs/functions/player.lua @@ -459,17 +459,6 @@ function Player.getSubjectVerb(self, past) return Pronouns.getPlayerSubjectVerb(self:getPronoun(), past) end -function Player.findItemInInbox(self, itemId) - local inbox = self:getStoreInbox() - local items = inbox:getItems() - for _, item in pairs(items) do - if item:getId() == itemId then - return item - end - end - return nil -end - function Player.updateHazard(self) local zones = self:getZones() if not zones or #zones == 0 then @@ -618,28 +607,6 @@ function Player:setFiendish() return false end -function Player:findItemInInbox(itemId, name) - local inbox = self:getStoreInbox() - local items = inbox:getItems() - for _, item in pairs(items) do - if item:getId() == itemId and (not name or item:getName() == name) then - return item - end - end - return nil -end - -function Player:sendColoredMessage(message) - local grey = 3003 - local blue = 3043 - local green = 3415 - local purple = 36792 - local yellow = 34021 - - local msg = message:gsub("{grey|", "{" .. grey .. "|"):gsub("{blue|", "{" .. blue .. "|"):gsub("{green|", "{" .. green .. "|"):gsub("{purple|", "{" .. purple .. "|"):gsub("{yellow|", "{" .. yellow .. "|") - return self:sendTextMessage(MESSAGE_LOOT, msg) -end - function Player:showInfoModal(title, message, buttonText) local modal = ModalWindow({ title = title, @@ -746,15 +713,6 @@ function Player.getNextRewardTime(self) return math.max(self:getStorageValue(DailyReward.storages.nextRewardTime), 0) end -function Player.isRestingAreaBonusActive(self) - local levelStreak = self:getStreakLevel() - if levelStreak > 1 then - return true - else - return false - end -end - function Player.getActiveDailyRewardBonusesName(self) local msg = "" local streakLevel = self:getStreakLevel() @@ -846,45 +804,6 @@ function Player.inBossFight(self) return false end --- For use of data/events/scripts/player.lua -function Player:executeRewardEvents(item, toPosition) - if toPosition.x == CONTAINER_POSITION then - local containerId = toPosition.y - 64 - local container = self:getContainerById(containerId) - if not container then - return true - end - - -- Do not let the player insert items into either the Reward Container or the Reward Chest - local itemId = container:getId() - if itemId == ITEM_REWARD_CONTAINER or itemId == ITEM_REWARD_CHEST then - self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - return false - end - - -- The player also shouldn't be able to insert items into the boss corpse - local tileCorpse = Tile(container:getPosition()) - for index, value in ipairs(tileCorpse:getItems() or {}) do - if value:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2 ^ 31 - 1 and value:getName() == container:getName() then - self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - return false - end - end - end - -- Do not let the player move the boss corpse. - if item:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) == 2 ^ 31 - 1 then - self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - return false - end - -- Players cannot throw items on reward chest - local tileChest = Tile(toPosition) - if tileChest and tileChest:getItemById(ITEM_REWARD_CHEST) then - self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - self:getPosition():sendMagicEffect(CONST_ME_POFF) - return false - end -end - do local loyaltySystem = { enable = configManager.getBoolean(configKeys.LOYALTY_ENABLED), @@ -987,3 +906,37 @@ function Player:canGetReward(rewardId, questName) return true end + +function Player.getURL(self) + local playerName = self:getName():gsub("%s+", "+") + local serverURL = configManager.getString(configKeys.URL) + + return serverURL .. "/characters/" .. playerName +end + +local emojiMap = { + ["knight"] = ":crossed_swords:", + ["paladin"] = ":bow_and_arrow:", + ["druid"] = ":herb:", + ["sorcerer"] = ":crystal_ball:", +} + +function Player.getMarkdownLink(self) + local vocation = self:vocationAbbrev() + local emoji = emojiMap[self:getVocation():getName():lower()] or ":school_satchel:" + local playerURL = self:getURL() + + return string.format("**[%s](%s)** %s [_%s_]", self:getName(), playerURL, emoji, vocation) +end + +function Player.findItemInInbox(self, itemId, name) + local inbox = self:getStoreInbox() + local items = inbox:getItems() + + for _, item in pairs(items) do + if item:getId() == itemId and (not name or item:getName() == name) then + return item + end + end + return nil +end diff --git a/data/modules/scripts/blessings/blessings.lua b/data/libs/systems/blessing.lua similarity index 50% rename from data/modules/scripts/blessings/blessings.lua rename to data/libs/systems/blessing.lua index e061501a330..f5403fbb07b 100644 --- a/data/modules/scripts/blessings/blessings.lua +++ b/data/libs/systems/blessing.lua @@ -6,29 +6,44 @@ Blessings.Credits = { lastUpdate = "08/04/2020", todo = { "Insert & Select query in blessings_history", - "Add unfair fight reductio (convert the get killer is pvp fight with getDamageMap of dead player)", - "Gamestore buy blessing", - "Test ank print text", - "Test all functions", - "Test henricus prices/blessings", - "Add data \\movements\\scripts\\quests\\cults of tibia\\icedeath.lua blessing information", - "WotE data\\movements\\scripts\\quests\\wrath of the emperor\\realmTeleport.lua has line checking if player has bless 1??? wtf", - "add blessings module support npc\\lib\\npcsystem\\modules.lua", - "Fix store buying bless", - "Check if store is inside lua or source...", }, } Blessings.Config = { AdventurerBlessingLevel = configManager.getNumber(configKeys.ADVENTURERSBLESSING_LEVEL), -- Free full bless until level HasToF = not configManager.getBoolean(configKeys.TOGGLE_SERVER_IS_RETRO), -- Enables/disables twist of fate - InquisitonBlessPriceMultiplier = 1.1, -- Bless price multiplied by henricus + InquisitonBlessPriceMultiplier = 1.1, -- Bless price multiplier by henricus SkulledDeathLoseStoreItem = configManager.getBoolean(configKeys.SKULLED_DEATH_LOSE_STORE_ITEM), -- Destroy all items on store when dying with red/blackskull - InventoryGlowOnFiveBless = configManager.getBoolean(configKeys.INVENTORY_GLOW), -- Glow in yellow inventory items when the player has 5 or more bless, - Debug = false, -- Prin debug messages in console if enabled } -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/assets.lua") +Blessings.Types = { + REGULAR = 1, + ENHANCED = 2, + PvP = 3, +} + +Blessings.All = { + [1] = { id = 1, name = "Twist of Fate", type = Blessings.Types.PvP }, + [2] = { id = 2, name = "The Wisdom of Solitude", charm = 10345, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, + [3] = { id = 3, name = "The Spark of the Phoenix", charm = 10341, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, + [4] = { id = 4, name = "The Fire of the Suns", charm = 10344, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, + [5] = { id = 5, name = "The Spiritual Shielding", charm = 10343, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, + [6] = { id = 6, name = "The Embrace of Tibia", charm = 10342, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, + [7] = { id = 7, name = "Heart of the Mountain", charm = 25360, type = Blessings.Types.ENHANCED, losscount = true, inquisition = false }, + [8] = { id = 8, name = "Blood of the Mountain", charm = 25361, type = Blessings.Types.ENHANCED, losscount = true, inquisition = false }, +} + +Blessings.LossPercent = { + [0] = { item = 100, skill = 0 }, + [1] = { item = 70, skill = 8 }, + [2] = { item = 45, skill = 16 }, + [3] = { item = 25, skill = 24 }, + [4] = { item = 10, skill = 32 }, + [5] = { item = 0, skill = 40 }, + [6] = { item = 0, skill = 48 }, + [7] = { item = 0, skill = 56 }, + [8] = { item = 0, skill = 56 }, +} --[=====[ -- @@ -45,9 +60,6 @@ CREATE TABLE IF NOT EXISTS `blessings_history` ( --]=====] Blessings.DebugPrint = function(content, pre, pos) - if not Blessings.Config.Debug then - return - end if pre == nil then pre = "" else @@ -67,145 +79,93 @@ Blessings.DebugPrint = function(content, pre, pos) end end -Blessings.C_Packet = { - OpenWindow = 0xCF, -} - -Blessings.S_Packet = { - BlessDialog = 0x9B, - BlessStatus = 0x9C, -} - -function onRecvbyte(player, msg, byte) - if byte == Blessings.C_Packet.OpenWindow then - Blessings.sendBlessDialog(player) - end -end - -Blessings.sendBlessStatus = function(player, curBless) - if player:getClient().version < 1200 then - return true - end - - -- why not using ProtocolGame::sendBlessStatus ? - local msg = NetworkMessage() - msg:addByte(Blessings.S_Packet.BlessStatus) - callback = function(k) - return true - end - if curBless == nil then - curBless = player:getBlessings(callback) -- ex: {1, 2, 5, 7} - end - Blessings.DebugPrint(#curBless, "sendBlessStatus curBless") - local bitWiseCurrentBless = 0 - local blessCount = 0 +Blessings.PlayerDeath = function(player, corpse, killer) + local hasAol = (player:getSlotItem(CONST_SLOT_NECKLACE) and player:getSlotItem(CONST_SLOT_NECKLACE):getId() == ITEM_AMULETOFLOSS) + local hasSkull = table.contains({ SKULL_RED, SKULL_BLACK }, player:getSkull()) + local currBlessCount = player:getBlessings() - for i = 1, #curBless do - if curBless[i].losscount then - blessCount = blessCount + 1 - end - if (not curBless[i].losscount and Blessings.Config.HasToF) or curBless[i].losscount then - bitWiseCurrentBless = bit.bor(bitWiseCurrentBless, Blessings.BitWiseTable[curBless[i].id]) - end + if hasSkull then + Blessings.DropLoot(player, corpse, 100, true) + elseif #currBlessCount < 5 and not hasAol then + local equipLossChance = Blessings.LossPercent[#currBlessCount].item + Blessings.DropLoot(player, corpse, equipLossChance) end - if blessCount > 5 and Blessings.Config.InventoryGlowOnFiveBless then - bitWiseCurrentBless = bit.bor(bitWiseCurrentBless, 1) + if not player:getSlotItem(CONST_SLOT_BACKPACK) then + player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) end - msg:addU16(bitWiseCurrentBless) - msg:addByte(blessCount >= 7 and 3 or (blessCount > 0 and 2 or 1)) -- Bless dialog button colour 1 = Disabled | 2 = normal | 3 = green - - -- if #curBless >= 5 then - -- msg:addU16(1) -- TODO ? - -- else - -- msg:addU16(0) - -- end - - msg:sendToPlayer(player) + return true end -Blessings.sendBlessDialog = function(player) - -- TODO: Migrate to protocolgame.cpp - local msg = NetworkMessage() - msg:addByte(Blessings.S_Packet.BlessDialog) +Blessings.DropLoot = function(player, corpse, chance, skulled) + local multiplier = 100 + math.randomseed(os.time()) + chance = chance * multiplier + Blessings.DebugPrint("DropLoot chance " .. chance) + for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do + local item = player:getSlotItem(i) + if item then + local thisChance = item:isContainer() and chance or (chance / 10) + local thisRandom = math.random(100 * multiplier) - callback = function(k) - return true - end - local curBless = player:getBlessings() - - msg:addByte(Blessings.Config.HasToF and #Blessings.All or (#Blessings.All - 1)) -- total blessings - for k = 1, #Blessings.All do - v = Blessings.All[k] - if v.type ~= Blessings.Types.PvP or Blessings.Config.HasToF then - msg:addU16(Blessings.BitWiseTable[v.id]) - msg:addByte(player:getBlessingCount(v.id)) - if player:getClient().version > 1200 then - msg:addByte(player:getBlessingCount(v.id, true)) -- Store Blessings Count + Blessings.DebugPrint(thisChance / multiplier .. "%" .. " | thisRandom " .. thisRandom / multiplier .. "%", "DropLoot item " .. item:getName() .. " |") + if skulled or thisRandom <= thisChance then + Blessings.DebugPrint("Dropped " .. item:getName()) + item:moveTo(corpse) end end end - local promotion = (player:isPremium() and player:isPromoted()) and 30 or 0 - local PvPminXPLoss = Blessings.LossPercent[#curBless].skill + promotion - local PvPmaxXPLoss = PvPminXPLoss - if Blessings.Config.HasToF then - PvPmaxXPLoss = math.floor(PvPminXPLoss * 1.15) - end - local PvEXPLoss = PvPminXPLoss - - local playerAmulet = player:getSlotItem(CONST_SLOT_NECKLACE) - local haveSkull = player:getSkull() >= 4 - hasAol = (playerAmulet and playerAmulet:getId() == ITEM_AMULETOFLOSS) - - equipLoss = Blessings.LossPercent[#curBless].item - if haveSkull then - equipLoss = 100 - elseif hasAol then - equipLoss = 0 - end - - msg:addByte(2) -- BYTE PREMIUM (only work with premium days) - msg:addByte(promotion) -- XP Loss Lower POR SER PREMIUM - msg:addByte(PvPminXPLoss) -- XP/Skill loss min pvp death - msg:addByte(PvPmaxXPLoss) -- XP/Skill loss max pvp death - msg:addByte(PvEXPLoss) -- XP/Skill pve death - msg:addByte(equipLoss) -- Equip container lose pvp death - msg:addByte(equipLoss) -- Equip container pve death - - msg:addByte(haveSkull and 1 or 0) -- is red/black skull - msg:addByte(hasAol and 1 or 0) - - -- History - local historyAmount = 1 - msg:addByte(historyAmount) -- History log count - for i = 1, historyAmount do - msg:addU32(os.time()) -- timestamp - msg:addByte(0) -- Color message (1 - Red | 0 = White loss) - msg:addString("Blessing Purchased", "Blessings.sendBlessDialog - Blessing Purchased") -- History message + if skulled and Blessings.Config.SkulledDeathLoseStoreItem then + local inbox = player:getStoreInbox() + local toBeDeleted = {} + if inbox and inbox:getSize() > 0 then + for i = 0, inbox:getSize() do + local item = inbox:getItem(i) + if item then + toBeDeleted[#toBeDeleted + 1] = item.uid + end + end + if #toBeDeleted > 0 then + for i, v in pairs(toBeDeleted) do + local item = Item(v) + if item then + item:remove() + end + end + end + end end - - msg:sendToPlayer(player) end +-- Blessing Helpers -- Blessings.getCommandFee = function(cost) local fee = configManager.getNumber(configKeys.BUY_BLESS_COMMAND_FEE) or 0 return cost + cost * (((fee > 100 and 100) or fee) / 100) end -Blessings.getBlessingsCost = function(level, byCommand) +Blessings.getBlessingCost = function(level, byCommand, enhanced) if byCommand == nil then byCommand = false end + + if enhanced == nil then + enhanced = false + end + local cost if level <= 30 then cost = 2000 elseif level >= 120 then - cost = 20000 + local base_cost = enhanced and 26000 or 20000 + local multiplier = enhanced and 100 or 75 + cost = base_cost + multiplier * (level - 120) else - cost = (level - 20) * 200 + local multiplier = enhanced and 260 or 200 + cost = multiplier * (level - 20) end + return byCommand and Blessings.getCommandFee(cost) or cost end @@ -213,6 +173,7 @@ Blessings.getPvpBlessingCost = function(level, byCommand) if byCommand == nil then byCommand = false end + local cost if level <= 30 then cost = 2000 @@ -221,6 +182,7 @@ Blessings.getPvpBlessingCost = function(level, byCommand) else cost = (level - 20) * 200 end + return byCommand and Blessings.getCommandFee(cost) or cost end @@ -250,6 +212,7 @@ Blessings.checkBless = function(player) for k, v in pairs(Blessings.All) do result = player:hasBlessing(k) and result .. "\n" .. v.name or result end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 20 > result:len() and "No blessings received." or result) return true end @@ -258,6 +221,7 @@ Blessings.doAdventurerBlessing = function(player) if player:getLevel() > Blessings.Config.AdventurerBlessingLevel then return true end + player:addMissingBless(true, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have adventurer's blessings for being level lower than " .. Blessings.Config.AdventurerBlessingLevel .. "!") @@ -270,70 +234,16 @@ Blessings.getInquisitionPrice = function(player) inquifilter = function(b) return b.inquisition end + donthavefilter = function(p, b) return not p:hasBlessing(b) end + local missing = #player:getBlessings(inquifilter, donthavefilter) - local totalBlessPrice = Blessings.getBlessingsCost(player:getLevel(), false) * missing * Blessings.Config.InquisitonBlessPriceMultiplier + local totalBlessPrice = Blessings.getBlessingCost(player:getLevel(), false) * missing * Blessings.Config.InquisitonBlessPriceMultiplier return missing, totalBlessPrice end -Blessings.DropLoot = function(player, corpse, chance, skulled) - local multiplier = 100 -- Improve the loot randomness spectrum - math.randomseed(os.time()) -- Improve the loot randomness spectrum - chance = chance * multiplier - Blessings.DebugPrint(chance, "DropLoot chance") - for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do - local item = player:getSlotItem(i) - if item then - local thisChance = chance - local thisRandom = math.random(100 * multiplier) - if not item:isContainer() then - thisChance = chance / 10 - end - Blessings.DebugPrint(thisChance / multiplier .. "%" .. " | thisRandom " .. thisRandom / multiplier .. "%", "DropLoot item " .. item:getName() .. " |") - if skulled or thisRandom <= thisChance then - Blessings.DebugPrint("Dropped " .. item:getName()) - item:moveTo(corpse) - end - end - end - if skulled and Blessings.Config.SkulledDeathLoseStoreItem then - local inbox = player:getStoreInbox() - local toBeDeleted = {} - if inbox and inbox:getSize() > 0 then - for i = 0, inbox:getSize() do - local item = inbox:getItem(i) - if item then - toBeDeleted[#toBeDeleted + 1] = item.uid - end - end - if #toBeDeleted > 0 then - for i, v in pairs(toBeDeleted) do - local item = Item(v) - if item then - item:remove() - end - end - end - end - end -end - -Blessings.ClearBless = function(player, killer, currentBless) - Blessings.DebugPrint(#currentBless, "ClearBless #currentBless") - local hasToF = Blessings.Config.HasToF and player:hasBlessing(1) or false - if hasToF and killer(killer:isPlayer() or (killer:getMaster() and killer:getMaster():isPlayer())) then -- TODO add better check if its pvp or pve - player:removeBlessing(1) - return - end - for i = 1, #currentBless do - Blessings.DebugPrint(i, "ClearBless curBless i", " | " .. currentBless[i].name) - player:removeBlessing(currentBless[i].id, 1) - end -end - --- bought by command Blessings.BuyAllBlesses = function(player) if not Tile(player:getPosition()):hasFlag(TILESTATE_PROTECTIONZONE) and (player:isPzLocked() or player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT)) then player:sendCancelMessage("You can't buy bless while in battle.") @@ -341,66 +251,49 @@ Blessings.BuyAllBlesses = function(player) return true end - local blessCost = Blessings.getBlessingsCost(player:getLevel(), true) - local PvPBlessCost = Blessings.getPvpBlessingCost(player:getLevel(), true) - local hasToF = Blessings.Config.HasToF and player:hasBlessing(1) or true donthavefilter = function(p, b) return not p:hasBlessing(b) end + + local hasToF = Blessings.Config.HasToF and player:hasBlessing(1) or true local missingBless = player:getBlessings(nil, donthavefilter) local missingBlessAmt = #missingBless + (hasToF and 0 or 1) - local totalCost = blessCost * #missingBless + local totalCost = 0 + + for _, bless in ipairs(missingBless) do + totalCost = totalCost + Blessings.getBlessingCost(player:getLevel(), true, bless.id >= 7) + end if missingBlessAmt == 0 then player:sendCancelMessage("You are already blessed.") player:getPosition():sendMagicEffect(CONST_ME_POFF) return true end + if not hasToF then - totalCost = totalCost + PvPBlessCost + totalCost = totalCost + Blessings.getPvpBlessingCost(player:getLevel(), true) end if player:removeMoneyBank(totalCost) then - metrics.addCounter("balance_decrease", remainsPrice, { + metrics.addCounter("balance_decrease", totalCost, { player = player:getName(), context = "blessings", }) - for i, v in ipairs(missingBless) do - player:addBlessing(v.id, 1) + + for _, bless in ipairs(missingBless) do + player:addBlessing(bless.id, 1) end - player:sendCancelMessage("You received the remaining " .. missingBlessAmt .. " blesses for a total of " .. totalCost .. " gold.") + + player:sendCancelMessage(string.format("You received the remaining %d blesses for a total of %d gold.", missingBlessAmt, totalCost)) player:getPosition():sendMagicEffect(CONST_ME_HOLYAREA) else - player:sendCancelMessage("You don't have enough money. You need " .. totalCost .. " to buy all blesses.", cid) + player:sendCancelMessage(string.format("You don't have enough money. You need %d to buy all blesses.", totalCost)) player:getPosition():sendMagicEffect(CONST_ME_POFF) end return true end -Blessings.PlayerDeath = function(player, corpse, killer) - local hasToF = Blessings.Config.HasToF and player:hasBlessing(1) or false - local hasAol = (player:getSlotItem(CONST_SLOT_NECKLACE) and player:getSlotItem(CONST_SLOT_NECKLACE):getId() == ITEM_AMULETOFLOSS) - local haveSkull = table.contains({ SKULL_RED, SKULL_BLACK }, player:getSkull()) - local curBless = player:getBlessings() - - if haveSkull then -- lose all bless + drop all items - Blessings.DropLoot(player, corpse, 100, true) - elseif #curBless < 5 and not hasAol then -- lose all items - local equipLoss = Blessings.LossPercent[#curBless].item - Blessings.DropLoot(player, corpse, equipLoss) - elseif #curBless < 5 and hasAol and not hasToF then - player:removeItem(ITEM_AMULETOFLOSS, 1, -1, false) - end - --Blessings.ClearBless(player, killer, curBless) IMPLEMENTED IN SOURCE BECAUSE THIS WAS HAPPENING BEFORE SKILL/EXP CALCULATIONS - - if not player:getSlotItem(CONST_SLOT_BACKPACK) then - player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) - end - - return true -end - function Player.getBlessings(self, filter, hasblessingFilter) local blessings = {} if filter == nil then @@ -414,11 +307,13 @@ function Player.getBlessings(self, filter, hasblessingFilter) return p:hasBlessing(b) end end + for k, v in pairs(Blessings.All) do if filter(v) and hasblessingFilter(self, k) then table.insert(blessings, v) end end + return blessings end @@ -426,11 +321,13 @@ function Player.addMissingBless(self, all, tof) if all == nil then all = true end + if tof == nil then tof = false elseif tof then tof = tof and Blessings.Config.HasToF end + for k, v in pairs(Blessings.All) do if all or (v.type == Blessings.Types.REGULAR) or (tof and v.type == Blessings.Types.PvP) then if not self:hasBlessing(k) then @@ -438,5 +335,5 @@ function Player.addMissingBless(self, all, tof) end end end - Blessings.sendBlessStatus(self) + self:sendBlessStatus() end diff --git a/data/libs/systems/load.lua b/data/libs/systems/load.lua index 281b8b1d466..ffe02320b96 100644 --- a/data/libs/systems/load.lua +++ b/data/libs/systems/load.lua @@ -1,4 +1,5 @@ -- Load systems functions +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") dofile(CORE_DIRECTORY .. "/libs/systems/concoctions.lua") dofile(CORE_DIRECTORY .. "/libs/systems/daily_reward.lua") dofile(CORE_DIRECTORY .. "/libs/systems/encounters.lua") diff --git a/data/libs/systems/vip.lua b/data/libs/systems/vip.lua index 9e76fd8ad80..49ef7bcf8cc 100644 --- a/data/libs/systems/vip.lua +++ b/data/libs/systems/vip.lua @@ -45,17 +45,17 @@ function Player.onAddVip(self, days, silent) self:kv():scoped("account"):set("vip-system", true) end -function CheckPremiumAndPrint(player, msgType) - if player:getVipDays() == 0xFFFF then - player:sendTextMessage(msgType, "You have an unlimited VIP status.") +function Player.sendVipStatus(self) + if self:getVipDays() == 0xFFFF then + self:sendTextMessage(MESSAGE_LOGIN, "You have unlimited VIP status.") return true end - local playerVipTime = player:getVipTime() + local playerVipTime = self:getVipTime() if playerVipTime < os.time() then - player:sendTextMessage(msgType, "Your VIP status is currently inactive.") + self:sendTextMessage(MESSAGE_STATUS, "Your VIP status is currently inactive.") return true end - player:sendTextMessage(msgType, string.format("You have %s of VIP time remaining.", getFormattedTimeRemaining(playerVipTime))) + self:sendTextMessage(MESSAGE_LOGIN, string.format("You have %s of VIP time remaining.", getFormattedTimeRemaining(playerVipTime))) end diff --git a/data/modules/modules.xml b/data/modules/modules.xml index c45646183ac..e51bf055f2a 100644 --- a/data/modules/modules.xml +++ b/data/modules/modules.xml @@ -10,9 +10,6 @@ - - - @@ -26,5 +23,4 @@ - diff --git a/data/modules/scripts/blessings/assets.lua b/data/modules/scripts/blessings/assets.lua deleted file mode 100644 index 73d02a272f3..00000000000 --- a/data/modules/scripts/blessings/assets.lua +++ /dev/null @@ -1,47 +0,0 @@ -Blessings.Types = { - REGULAR = 1, - ENHANCED = 2, - PvP = 3, -} - -Blessings.All = { - [1] = { id = 1, name = "Twist of Fate", type = Blessings.Types.PvP }, - [2] = { id = 2, name = "The Wisdom of Solitude", charm = 10345, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, - [3] = { id = 3, name = "The Spark of the Phoenix", charm = 10341, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, - [4] = { id = 4, name = "The Fire of the Suns", charm = 10344, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, - [5] = { id = 5, name = "The Spiritual Shielding", charm = 10343, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, - [6] = { id = 6, name = "The Embrace of Tibia", charm = 10342, type = Blessings.Types.REGULAR, losscount = true, inquisition = true }, - [7] = { id = 7, name = "Blood of the Mountain", charm = 25360, type = Blessings.Types.ENHANCED, losscount = true, inquisition = false }, - [8] = { id = 8, name = "Heart of the Mountain", charm = 25361, type = Blessings.Types.ENHANCED, losscount = true, inquisition = false }, -} - -Blessings.LossPercent = { - [0] = { item = 100, skill = 0 }, - [1] = { item = 70, skill = 8 }, - [2] = { item = 45, skill = 16 }, - [3] = { item = 25, skill = 24 }, - [4] = { item = 10, skill = 32 }, - [5] = { item = 0, skill = 40 }, - [6] = { item = 0, skill = 48 }, - [7] = { item = 0, skill = 56 }, - [8] = { item = 0, skill = 56 }, -} - -Blessings.BitWiseTable = { - [0] = 1, - [1] = 2, - [2] = 4, - [3] = 8, - [4] = 16, - [5] = 32, - [6] = 64, - [7] = 128, - [8] = 256, - [9] = 512, - [10] = 1024, - [11] = 2048, - [12] = 4096, - [13] = 8192, - [14] = 16384, - [15] = 32768, -} diff --git a/data/modules/scripts/cults_of_tibia/death.lua b/data/modules/scripts/cults_of_tibia/death.lua index a9a855a9471..c27a9926171 100644 --- a/data/modules/scripts/cults_of_tibia/death.lua +++ b/data/modules/scripts/cults_of_tibia/death.lua @@ -1,8 +1,8 @@ function onRecvbyte(player, msg, byte) if IsRunningGlobalDatapack() and player then - local storageDeathFake = player:getStorageValue(Storage.CultsOfTibia.Barkless.Death) + local storageDeathFake = player:getStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Death) if storageDeathFake == 1 then - player:setStorageValue(Storage.CultsOfTibia.Barkless.Death, 0) + player:setStorageValue(Storage.Quest.U11_40.CultsOfTibia.Barkless.Death, 0) player:addHealth(player:getMaxHealth()) player:addMana(player:getMaxMana()) player:setHiddenHealth(false) diff --git a/data/npclib/npc.lua b/data/npclib/npc.lua index 4de60c45c49..4a8097ff27f 100644 --- a/data/npclib/npc.lua +++ b/data/npclib/npc.lua @@ -89,7 +89,7 @@ function SayEvent(npcId, playerId, messageDelayed, npcHandler, textType) local parseInfo = { [TAG_PLAYERNAME] = player:getName(), [TAG_TIME] = getFormattedWorldTime(), - [TAG_BLESSCOST] = Blessings.getBlessingsCost(player:getLevel(), false), + [TAG_BLESSCOST] = Blessings.getBlessingCost(player:getLevel(), false, (npc:getName() == "Kais" or npc:getName() == "Nomad") and true), [TAG_PVPBLESSCOST] = Blessings.getPvpBlessingCost(player:getLevel(), false), } npc:say(npcHandler:parseMessage(messageDelayed, parseInfo), textType or TALKTYPE_PRIVATE_NP, false, player, npc:getPosition()) diff --git a/data/npclib/npc_system/modules.lua b/data/npclib/npc_system/modules.lua index aca92804e80..08027a67d2b 100644 --- a/data/npclib/npc_system/modules.lua +++ b/data/npclib/npc_system/modules.lua @@ -60,7 +60,7 @@ if Modules == nil then local parseInfo = { [TAG_PLAYERNAME] = player:getName(), [TAG_TIME] = getFormattedWorldTime(), - [TAG_BLESSCOST] = Blessings.getBlessingsCost(player:getLevel(), false), + [TAG_BLESSCOST] = Blessings.getBlessingCost(player:getLevel(), false, (npc:getName() == "Kais" or npc:getName() == "Nomad") and true), [TAG_PVPBLESSCOST] = Blessings.getPvpBlessingCost(player:getLevel(), false), [TAG_TRAVELCOST] = costMessage, } @@ -160,7 +160,7 @@ if Modules == nil then end local parseInfo = { - [TAG_BLESSCOST] = Blessings.getBlessingsCost(player:getLevel(), false), + [TAG_BLESSCOST] = Blessings.getBlessingCost(player:getLevel(), false, (npc:getName() == "Kais" or npc:getName() == "Nomad") and true), [TAG_PVPBLESSCOST] = Blessings.getPvpBlessingCost(player:getLevel(), false), } if player:hasBlessing(parameters.bless) then @@ -175,7 +175,7 @@ if Modules == nil then npc, player ) - elseif not player:removeMoneyBank(type(parameters.cost) == "string" and npcHandler:parseMessage(parameters.cost, parseInfo) or parameters.cost) then + elseif not player:removeMoneyBank(type(parameters.cost) == "string" and tonumber(npcHandler:parseMessage(parameters.cost, parseInfo)) or parameters.cost) then npcHandler:say("Oh. You do not have enough money.", npc, player) else npcHandler:say(parameters.text or "You have been blessed by one of the seven gods!", npc, player) diff --git a/data-otservbr-global/scripts/actions/other/balloons.lua b/data/scripts/actions/items/anniversary_balloons.lua similarity index 79% rename from data-otservbr-global/scripts/actions/other/balloons.lua rename to data/scripts/actions/items/anniversary_balloons.lua index 35e84eec531..8fbeecee110 100644 --- a/data-otservbr-global/scripts/actions/other/balloons.lua +++ b/data/scripts/actions/items/anniversary_balloons.lua @@ -1,4 +1,4 @@ -local balloonItems = { +local settings = { [37471] = 37414, [37414] = 37471, -- blue balloon [37472] = 37416, @@ -77,32 +77,28 @@ local balloonItems = { [39692] = 39680, -- balloon no.9 } -local balloons = Action() +local anniversaryBalloons = Action() -function balloons.onUse(player, item, fp, target, toPosition, isHotkey) - local balloon = balloonItems[item.itemid] +function anniversaryBalloons.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local balloon = settings[item.itemid] if not balloon then - return false + return true end local fromPosition = item:getPosition() local tile = Tile(fromPosition) - if not fromPosition:getTile():getHouse() then + + if not tile:getHouse() then player:sendTextMessage(MESSAGE_FAILURE, "You may use this only inside a house.") - elseif tile:getItemCountById(item.itemid) == 1 then - for index, value in pairs(balloonItems) do - if tile:getItemCountById(index) > 0 and index ~= item.itemid then - player:sendCancelMessage(Game.getReturnMessage(RETURNVALUE_NOTPOSSIBLE)) - return true - end - end - item:transform(balloon) + return true end + + item:transform(balloon, 1) return true end -for index, value in pairs(balloonItems) do - balloons:id(index) +for itemId in pairs(settings) do + anniversaryBalloons:id(itemId) end -balloons:register() +anniversaryBalloons:register() diff --git a/data-canary/scripts/actions/other/bed_modification_kits.lua b/data/scripts/actions/items/bed_modification_kits.lua similarity index 90% rename from data-canary/scripts/actions/other/bed_modification_kits.lua rename to data/scripts/actions/items/bed_modification_kits.lua index 431e3cef5eb..a406f7fd5b2 100644 --- a/data-canary/scripts/actions/other/bed_modification_kits.lua +++ b/data/scripts/actions/items/bed_modification_kits.lua @@ -20,7 +20,7 @@ local bedModificationKits = Action() function bedModificationKits.onUse(player, item, fromPosition, target, toPosition, isHotkey) local newBed = setting[item:getId()] - if not newBed or type(target) ~= "userdata" or not target:isItem() then + if not newBed or not target or not target:isItem() then return false end @@ -35,7 +35,7 @@ function bedModificationKits.onUse(player, item, fromPosition, target, toPositio return true end - for index, value in pairs(setting) do + for _, value in pairs(setting) do if value[1][1] == targetItemId or table.contains({ 2491, 5501, 15506 }, targetItemId) then toPosition:sendMagicEffect(CONST_ME_POFF) toPosition.y = toPosition.y + 1 @@ -51,8 +51,8 @@ function bedModificationKits.onUse(player, item, fromPosition, target, toPositio return true end -for index, value in pairs(setting) do - bedModificationKits:id(index) +for id in pairs(setting) do + bedModificationKits:id(id) end bedModificationKits:register() diff --git a/data/scripts/actions/items/blessing_charms.lua b/data/scripts/actions/items/blessing_charms.lua index 7e70c5a6719..fdca561c3a2 100644 --- a/data/scripts/actions/items/blessing_charms.lua +++ b/data/scripts/actions/items/blessing_charms.lua @@ -1,4 +1,4 @@ -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") local blessingCharms = Action() diff --git a/data/scripts/actions/items/check_bless.lua b/data/scripts/actions/items/check_bless.lua index 0d2478f5f11..09d07fffd85 100644 --- a/data/scripts/actions/items/check_bless.lua +++ b/data/scripts/actions/items/check_bless.lua @@ -1,4 +1,4 @@ -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") local checkBless = Action() diff --git a/data/scripts/actions/items/christmas_bundle.lua b/data/scripts/actions/items/christmas_bundle.lua new file mode 100644 index 00000000000..d0a56f6d050 --- /dev/null +++ b/data/scripts/actions/items/christmas_bundle.lua @@ -0,0 +1,42 @@ +local setting = { + [6506] = { { 6569, 15 }, { 3585, 5 }, { 3586, 10 }, { 3598, 20 }, { 3599, 10 }, 6500, 6501, 6489, 6503, 6387 }, -- red bundle + [6507] = { { 6569, 15 }, { 3585, 5 }, { 3586, 10 }, { 3598, 20 }, { 3599, 10 }, 6500, 6501, 6489, 6505, 6387 }, -- blue bundle + [6508] = { { 6569, 15 }, { 3585, 5 }, { 3586, 10 }, { 3598, 20 }, { 3599, 10 }, 6500, 6501, 6489, 6502, 6387 }, -- green bundle +} + +local christmasBundle = Action() + +function christmasBundle.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local targetItem = setting[item.itemid] + if not targetItem then + return true + end + + local rewards = {} + while #rewards < 7 do + local randIndex = math.random(#targetItem) + local gift = targetItem[randIndex] + + local count = 1 + if type(gift) == "table" then + gift, count = unpack(gift) + end + + rewards[#rewards + 1] = { gift, count } + table.remove(targetItem, randIndex) + end + + for _, reward in ipairs(rewards) do + player:addItem(unpack(reward)) + end + + player:getPosition():sendMagicEffect(CONST_ME_GIFT_WRAPS) + item:remove(1) + return true +end + +for itemId in pairs(setting) do + christmasBundle:id(itemId) +end + +christmasBundle:register() diff --git a/data/scripts/actions/items/cobra_flask.lua b/data/scripts/actions/items/cobra_flask.lua index c36d42983c5..0556373afae 100644 --- a/data/scripts/actions/items/cobra_flask.lua +++ b/data/scripts/actions/items/cobra_flask.lua @@ -1,19 +1,3 @@ -local applyCobraFlaskEffectOnMonsterSpawn = EventCallback("CobraFlaskEffectOnMonsterSpawn") - -applyCobraFlaskEffectOnMonsterSpawn.monsterOnSpawn = function(monster, position) - if table.contains({ "cobra scout", "cobra vizier", "cobra assassin" }, monster:getName():lower()) then - if Game.getStorageValue(Global.Storage.CobraFlask) >= os.time() then - monster:setHealth(monster:getMaxHealth() * 0.75) - monster:getPosition():sendMagicEffect(CONST_ME_GREEN_RINGS) - else - Game.setStorageValue(Global.Storage.CobraFlask, -1) - end - end - return true -end - -applyCobraFlaskEffectOnMonsterSpawn:register() - local cobraFlask = Action() function cobraFlask.onUse(player, item, fromPosition, target, toPosition, isHotkey) diff --git a/data-canary/scripts/actions/other/decay_to.lua b/data/scripts/actions/items/decay_to.lua similarity index 87% rename from data-canary/scripts/actions/other/decay_to.lua rename to data/scripts/actions/items/decay_to.lua index bfceedb288e..bb68e346e1f 100644 --- a/data-canary/scripts/actions/other/decay_to.lua +++ b/data/scripts/actions/items/decay_to.lua @@ -1,5 +1,9 @@ -local setting = { - --[itemid] = decayto +local voices = { + [23708] = "Au au!", + [23443] = "Grooaarr!", +} + +local transformItems = { [2062] = 2063, [2063] = 2062, -- sacred statue [2064] = 2065, @@ -439,16 +443,69 @@ local setting = { [39700] = 39699, -- rainbow torch [39701] = 39702, [39702] = 39701, -- rainbow torch + [39757] = 39758, -- yeti doll + [39759] = 39760, + [39761] = 39762, -- the gods' twilight doll + [39772] = 39773, + [39773] = 39774, -- flower table + [39774] = 39772, -- flower table + [39793] = 39794, + [39794] = 39793, -- turquoise flower lamp + [39795] = 39796, + [39796] = 39795, -- purple flower lamp + [39801] = 39802, + [39802] = 39801, -- wall leaves + [39803] = 39804, + [39804] = 39803, -- tendrils + [39805] = 39806, + [39807] = 39808, -- water nymph + [39810] = 39809, -- water nymph + [42271] = 42272, + [42272] = 42271, -- seafarer table + [42291] = 42292, + [42292] = 42291, -- seashell lamp + [42293] = 42294, + [42294] = 42293, -- seashell lamp + [42295] = 42296, + [42296] = 42295, -- tentacle lamp + [42297] = 42298, + [42298] = 42297, -- tentacle lamp + [42299] = 42300, + [42300] = 42299, -- sea-devil wall lamp + [42301] = 42302, + [42302] = 42301, -- seafood bucket + [42324] = 42326, + [42326] = 42324, -- opulent table + [42325] = 42327, + [42327] = 42325, -- opulent table + [42346] = 42347, + [42347] = 42346, -- opulent floor lamp + [42348] = 42349, + [42349] = 42348, -- opulent floor lamp + [42363] = 42364, -- djinn lamp + [42365] = 42366, -- djinn lamp } local decayTo = Action() function decayTo.onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(setting[item.itemid]) + local itemId = item:getId() + if voices[itemId] then + local spectators = Game.getSpectators(fromPosition, false, true, 3, 3) + for _, spectator in ipairs(spectators) do + player:say(voices[itemId], TALKTYPE_MONSTER_SAY, false, spectator, fromPosition) + end + end + + local newItemId = transformItems[itemId] + if newItemId then + item:transform(newItemId) + item:decay() + end return true end -for index, value in pairs(setting) do +for index in pairs(transformItems) do decayTo:id(index) end diff --git a/data-canary/scripts/actions/other/dolls.lua b/data/scripts/actions/items/dolls.lua similarity index 100% rename from data-canary/scripts/actions/other/dolls.lua rename to data/scripts/actions/items/dolls.lua diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_amulet.lua b/data/scripts/actions/items/ferumbras_amulet.lua similarity index 95% rename from data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_amulet.lua rename to data/scripts/actions/items/ferumbras_amulet.lua index d92c496e165..dee32339a46 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_amulet.lua +++ b/data/scripts/actions/items/ferumbras_amulet.lua @@ -1,10 +1,12 @@ local ferumbrasAscendantAmulet = Action() + function ferumbrasAscendantAmulet.onUse(player, item, fromPosition, target, toPosition, isHotkey) local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) - if amulet ~= item or amulet ~= item then + if amulet ~= item then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to equip the amulet to try use it.") return true end + if item.itemid == 22767 then if math.random(2) == 1 then player:addHealth(1000, true, true) @@ -13,10 +15,10 @@ function ferumbrasAscendantAmulet.onUse(player, item, fromPosition, target, toPo player:addMana(1000, true, true) player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Magical sparks whirl around the amulet as you use it and you was restored.") end + item:transform(22768) item:decay() player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) - return true elseif item.itemid == 22768 then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are tired of the last use of the amulet, you must wait for the recharge.") end diff --git a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_mana_keg.lua b/data/scripts/actions/items/ferumbras_mana_keg.lua similarity index 99% rename from data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_mana_keg.lua rename to data/scripts/actions/items/ferumbras_mana_keg.lua index 8ece01ed6e8..04bbc7b6e50 100644 --- a/data-otservbr-global/scripts/quests/ferumbras_ascension/actions_ferumbras_mana_keg.lua +++ b/data/scripts/actions/items/ferumbras_mana_keg.lua @@ -1,4 +1,5 @@ local ferumbrasAscendantManaKeg = Action() + function ferumbrasAscendantManaKeg.onUse(player, item, fromPosition, target, toPosition, isHotkey) if item.itemid == 22769 then player:addItem("ultimate mana potion", 10) diff --git a/data-canary/scripts/actions/other/ladder_up.lua b/data/scripts/actions/items/ladder_up.lua similarity index 64% rename from data-canary/scripts/actions/other/ladder_up.lua rename to data/scripts/actions/items/ladder_up.lua index efea920c9b8..5ec5f7c5b67 100644 --- a/data-canary/scripts/actions/other/ladder_up.lua +++ b/data/scripts/actions/items/ladder_up.lua @@ -1,9 +1,9 @@ -local setting = { 1948, 1968, 5542, 20474, 20475, 28656, 31262 } +local ladderTable = Game.getLadderIds() local ladder = Action() function ladder.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if table.contains(setting, item.itemid) then + if table.contains(ladderTable, item.itemid) then fromPosition:moveUpstairs() else fromPosition.z = fromPosition.z + 1 @@ -14,12 +14,9 @@ function ladder.onUse(player, item, fromPosition, target, toPosition, isHotkey) return true end - player:teleportTo(fromPosition, false) + player:teleportTo(fromPosition, true) return true end -for index, value in ipairs(setting) do - ladder:id(value) -end - +ladder:id(435, unpack(ladderTable)) ladder:register() diff --git a/data-otservbr-global/scripts/actions/other/party_trumpet.lua b/data/scripts/actions/items/party_trumpet.lua similarity index 100% rename from data-otservbr-global/scripts/actions/other/party_trumpet.lua rename to data/scripts/actions/items/party_trumpet.lua index 71ee617ec69..a1cb77bf56d 100644 --- a/data-otservbr-global/scripts/actions/other/party_trumpet.lua +++ b/data/scripts/actions/items/party_trumpet.lua @@ -1,10 +1,10 @@ local partyTrumpet = Action() function partyTrumpet.onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(6573) - item:decay() player:say("TOOOOOOT!", TALKTYPE_MONSTER_SAY) fromPosition:sendMagicEffect(CONST_ME_SOUND_BLUE) + item:transform(6573) + item:decay() return true end diff --git a/data-otservbr-global/scripts/actions/other/roasted_meat.lua b/data/scripts/actions/items/roasted_meat.lua similarity index 100% rename from data-otservbr-global/scripts/actions/other/roasted_meat.lua rename to data/scripts/actions/items/roasted_meat.lua diff --git a/data/scripts/actions/items/surprise_bags.lua b/data/scripts/actions/items/surprise_bags.lua new file mode 100644 index 00000000000..09c03e516db --- /dev/null +++ b/data/scripts/actions/items/surprise_bags.lua @@ -0,0 +1,32 @@ +local settings = { + [6570] = { { 3598, 10 }, 6393, 6279, 6574, 6578, 6575, 6577, 6569, 6576, 6572, 2995, 14027, 14681 }, -- blue present + [6571] = { 6574, 3079, 6393, 6576, 6578, 2995, 14027, 3036, 5944, 3386, 3420, 3039, 5080, 2993, 3392, 3057, 5791 }, -- red present + [8853] = { { 3031, 10 }, 123, 2995, 2397, 651, 3218, 6574, 6393, 7377, 3578, 8778 }, -- surprise bag + [14751] = { { 9642, 15 }, { 3581, 15 }, 5917, 3273, 10302, 9019, 5928, 5926, 5927, 6095, 5918, 6097, 6098, 5461, 5090 }, -- surprise bag + [14759] = { { 6569, 10 }, { 6541, 10 }, { 6542, 10 }, { 6543, 10 }, { 6544, 10 }, { 6545, 10 }, 6574, 4839, 6570, 6571, 3215 }, -- surprise bag +} + +local surpriseBag = Action() + +function surpriseBag.onUse(player, item, fromPosition) + local present = settings[item.itemid] + if not present then + return true + end + + local gift = present[math.random(#present)] + local count = 1 + + if type(gift) == "table" then + count = math.random(gift[2]) + gift = gift[1] + end + + player:addItem(gift, count) + fromPosition:sendMagicEffect(CONST_ME_GIFT_WRAPS) + item:remove(1) + return true +end + +surpriseBag:id(6570, 6571, 8853, 14751, 14759) +surpriseBag:register() diff --git a/data/scripts/actions/items/surprise_music_box.lua b/data/scripts/actions/items/surprise_music_box.lua new file mode 100644 index 00000000000..05abbac3d08 --- /dev/null +++ b/data/scripts/actions/items/surprise_music_box.lua @@ -0,0 +1,34 @@ +local prize = { + { chance = 1, id = 3246, amount = 1 }, + { chance = 2, id = 10227, amount = 1 }, + { chance = 3, id = 11588, amount = 1 }, + { chance = 4, id = 3549, amount = 1 }, + { chance = 5, id = 3420, amount = 1 }, + { chance = 10, id = ITEM_CRYSTAL_COIN, amount = 17 }, + { chance = 20, id = ITEM_GOLD_COIN, amount = 1 }, + { chance = 30, id = ITEM_CRYSTAL_COIN, amount = 1 }, + { chance = 40, id = ITEM_GOLD_COIN, amount = 50 }, + { chance = 50, id = ITEM_PLATINUM_COIN, amount = 15 }, + { chance = 90, id = ITEM_GOLD_COIN, amount = 80 }, +} + +local surpriseBox = Action() + +function surpriseBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local number = math.random(1, 100) + local cumulativeChance = 0 + + for _, prizeEntry in ipairs(prize) do + cumulativeChance = cumulativeChance + prizeEntry.chance + if number <= cumulativeChance then + player:getPosition():sendMagicEffect(CONST_ME_POFF) + player:addItem(prizeEntry.id, prizeEntry.amount) + item:remove() + break + end + end + return true +end + +surpriseBox:id(12045) +surpriseBox:register() diff --git a/data/scripts/actions/items/usable_phantasmal_jade_items.lua b/data/scripts/actions/items/usable_phantasmal_jade_items.lua new file mode 100644 index 00000000000..8075125df25 --- /dev/null +++ b/data/scripts/actions/items/usable_phantasmal_jade_items.lua @@ -0,0 +1,45 @@ +local config = { + requiredItems = { + [34072] = { key = "spectral-horseshoes", count = 4 }, + [34073] = { key = "spectral-saddle", count = 1 }, + [34074] = { key = "spectral-horse-tac", count = 1 }, + }, + + mountId = 167, +} + +local usablePhantasmalJadeItems = Action() + +function usablePhantasmalJadeItems.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local itemInfo = config.requiredItems[item:getId()] + if not itemInfo then + return true + end + + if player:hasMount(config.mountId) then + return true + end + + local currentCount = (player:kv():get(itemInfo.key) or 0) + 1 + player:kv():set(itemInfo.key, currentCount) + player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE) + item:remove(1) + + for _, info in pairs(config.requiredItems) do + if (player:kv():get(info.key) or 0) < info.count then + return true + end + end + + player:addMount(config.mountId) + player:addAchievement("Natural Born Cowboy") + player:addAchievement("You got Horse Power") + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Phantasmal jade is now yours!") + return true +end + +for itemId, _ in pairs(config.requiredItems) do + usablePhantasmalJadeItems:id(itemId) +end + +usablePhantasmalJadeItems:register() diff --git a/data/scripts/actions/items/vessels.lua b/data/scripts/actions/items/vessels.lua new file mode 100644 index 00000000000..2d6fe19bf00 --- /dev/null +++ b/data/scripts/actions/items/vessels.lua @@ -0,0 +1,26 @@ +local config = { + [37572] = CONST_ME_GAZHARAGOTH, + [37573] = CONST_ME_FERUMBRAS_1, + [37574] = CONST_ME_MAD_MAGE, + [37575] = CONST_ME_HORESTIS, + [37576] = CONST_ME_DEVOVORGA, +} + +local vessels = Action() + +function vessels.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local vessel = config[item.itemid] + if not vessel or not target:isPlayer() then + return true + end + + toPosition:sendMagicEffect(vessel) + item:remove(1) + return true +end + +for index in pairs(config) do + vessels:id(index) +end + +vessels:register() diff --git a/data-otservbr-global/scripts/actions/other/bath_tub.lua b/data/scripts/actions/objects/bath_tub_drain.lua similarity index 99% rename from data-otservbr-global/scripts/actions/other/bath_tub.lua rename to data/scripts/actions/objects/bath_tub_drain.lua index cd1b3238ca6..a09886a2ad1 100644 --- a/data-otservbr-global/scripts/actions/other/bath_tub.lua +++ b/data/scripts/actions/objects/bath_tub_drain.lua @@ -1,4 +1,5 @@ local bathtubDrain = Action() + function bathtubDrain.onUse(player, item, fromPosition, itemEx, toPosition) local tile = Tile(fromPosition) if tile:getTopCreature() then diff --git a/data/scripts/actions/tools/crushers.lua b/data/scripts/actions/tools/crushers.lua new file mode 100644 index 00000000000..99c3102616d --- /dev/null +++ b/data/scripts/actions/tools/crushers.lua @@ -0,0 +1,86 @@ +local config = { + maxGemBreak = 10, + fragmentGems = { + small = { ids = { 44602, 44605, 44608, 44611 }, fragment = 46625, range = { 1, 4 } }, + medium = { ids = { 44603, 44606, 44609, 44612 }, fragment = 46625, range = { 2, 8 } }, + great = { ids = { 44604, 44607, 44610, 44613 }, fragment = 46626, range = { 1, 4 } }, + }, +} + +local function getGemData(gemId) + for _, gemData in pairs(config.fragmentGems) do + if table.contains(gemData.ids, gemId) then + return gemData.fragment, gemData.range + end + end + return nil +end + +local amberCrusher = Action() + +function amberCrusher.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not target or not target:isItem() or target:getId() == item:getId() or player:getItemCount(target:getId()) <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use the crusher on a valid gem in your inventory.") + return true + end + + local fragmentType, fragmentRange = getGemData(target:getId()) + if not fragmentType then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This item can't be broken into fragments.") + return true + end + + local breakAmount = (target:getCount() >= config.maxGemBreak) and config.maxGemBreak or 1 + target:remove(breakAmount) + + for _ = 1, breakAmount do + player:addItem(fragmentType, math.random(fragmentRange[1], fragmentRange[2])) + end + + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have broken the gem into fragments.") + return true +end + +amberCrusher:id(46628) +amberCrusher:register() + +local crusher = Action() + +function crusher.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if not target or not target:isItem() or target:getId() == item:getId() or player:getItemCount(target:getId()) <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can only use the crusher on a valid gem in your inventory.") + return true + end + + local fragmentType, fragmentRange = getGemData(target:getId()) + if not fragmentType then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This item can't be broken into fragments.") + return true + end + + local crusherCharges = item:getAttribute(ITEM_ATTRIBUTE_CHARGES) + if not crusherCharges or crusherCharges <= 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your crusher has no more charges.") + return true + end + + target:remove(1) + player:addItem(fragmentType, math.random(fragmentRange[1], fragmentRange[2])) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have broken the gem into fragments.") + + crusherCharges = crusherCharges - 1 + if crusherCharges > 0 then + local container = item:getParent() + item:setAttribute(ITEM_ATTRIBUTE_CHARGES, crusherCharges) + if container:isContainer() then + player:sendUpdateContainer(container) + end + else + item:remove() + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your crusher has been consumed.") + end + return true +end + +crusher:id(46627) +crusher:register() diff --git a/data/scripts/creaturescripts/monster/boss_lever_death.lua b/data/scripts/creaturescripts/monster/boss_lever_death.lua index 4e035271623..35a86a97e92 100644 --- a/data/scripts/creaturescripts/monster/boss_lever_death.lua +++ b/data/scripts/creaturescripts/monster/boss_lever_death.lua @@ -13,7 +13,7 @@ function onBossDeath.onDeath(creature) return true end - local bossLever = BossLever[name] + local bossLever = BossLever[name:lower()] if not bossLever then return true end diff --git a/data-otservbr-global/scripts/creaturescripts/monster/spawn_system.lua b/data/scripts/creaturescripts/monster/spawn_system.lua similarity index 99% rename from data-otservbr-global/scripts/creaturescripts/monster/spawn_system.lua rename to data/scripts/creaturescripts/monster/spawn_system.lua index 580dba6d07c..710585cced3 100644 --- a/data-otservbr-global/scripts/creaturescripts/monster/spawn_system.lua +++ b/data/scripts/creaturescripts/monster/spawn_system.lua @@ -1,4 +1,5 @@ local monsterDeath = CreatureEvent("monsterDeath") + function monsterDeath.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamageUnjustified) if creature and creature:isMonster() then local self = creature:getStorageValue(MonsterStorage.Spawn.monster_spawn_object) @@ -12,6 +13,7 @@ end monsterDeath:register() local monsterDeathBoss = CreatureEvent("monsterDeathBoss") + function monsterDeathBoss.onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamageUnjustified) if creature and creature:isMonster() then local self = creature:getStorageValue(MonsterStorage.Spawn.monster_spawn_object) diff --git a/data-canary/scripts/creaturescripts/extended_opcode.lua b/data/scripts/creaturescripts/others/#extended_opcode.lua similarity index 100% rename from data-canary/scripts/creaturescripts/extended_opcode.lua rename to data/scripts/creaturescripts/others/#extended_opcode.lua diff --git a/data/scripts/creaturescripts/player/adventure_blessing_login.lua b/data/scripts/creaturescripts/player/adventure_blessing_login.lua index 8ebf88a72e9..79c694d73bc 100644 --- a/data/scripts/creaturescripts/player/adventure_blessing_login.lua +++ b/data/scripts/creaturescripts/player/adventure_blessing_login.lua @@ -1,4 +1,4 @@ -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") local adventurerBlessingLogin = CreatureEvent("AdventurerBlessingLogin") diff --git a/data/scripts/creaturescripts/player/login.lua b/data/scripts/creaturescripts/player/login.lua index 5f9f0e695f4..fe52be71b06 100644 --- a/data/scripts/creaturescripts/player/login.lua +++ b/data/scripts/creaturescripts/player/login.lua @@ -80,7 +80,7 @@ function playerLoginGlobal.onLogin(player) end -- Send Recruiter Outfit - local resultId = db.storeQuery("SELECT `recruiter` FROM `accounts` WHERE `id`= " .. getAccountNumberByPlayerName(getPlayerName(player))) + local resultId = db.storeQuery("SELECT `recruiter` FROM `accounts` WHERE `id`= " .. Game.getPlayerAccountId(getPlayerName(player))) if resultId then local recruiterStatus = Result.getNumber(resultId, "recruiter") local sex = player:getSex() @@ -118,19 +118,19 @@ function playerLoginGlobal.onLogin(player) -- Updates the player's VIP status and executes corresponding actions if applicable. if configManager.getBoolean(configKeys.VIP_SYSTEM_ENABLED) then - local isVipNow = player:isVip() - local wasVip = player:kv():scoped("account"):get("vip-system") or false + local isCurrentlyVip = player:isVip() + local hadVipStatus = player:kv():scoped("account"):get("vip-system") or false - if wasVip ~= isVipNow then - if wasVip then + if hadVipStatus ~= isCurrentlyVip then + if hadVipStatus then player:onRemoveVip() else player:onAddVip(player:getVipDays()) end end - if isVipNow then - CheckPremiumAndPrint(player, MESSAGE_LOGIN) + if isCurrentlyVip then + player:sendVipStatus() end end diff --git a/data/scripts/eventcallbacks/README.md b/data/scripts/eventcallbacks/README.md index 6e0bacfcd6e..bbcee5de3c4 100644 --- a/data/scripts/eventcallbacks/README.md +++ b/data/scripts/eventcallbacks/README.md @@ -16,7 +16,6 @@ Event callbacks are available for several categories of game entities, such as ` - `(bool)` `creatureOnChangeOutfit` - `(ReturnValue)` `creatureOnAreaCombat` - `(ReturnValue)` `creatureOnTargetCombat` -- `(void)` `creatureOnHear` - `(void)` `creatureOnDrainHealth` - `(void)` `creatureOnCombat` - `(bool)` `partyOnJoin` @@ -51,8 +50,6 @@ Event callbacks are available for several categories of game entities, such as ` - `(void)` `playerOnWalk` - `(void)` `monsterOnDropLoot` - `(void)` `monsterPostDropLoot` -- `(void)` `monsterOnSpawn` -- `(void)` `npcOnSpawn` ## Event Callback Usage @@ -102,20 +99,8 @@ callback:register() ```lua local callback = EventCallback("UniqueCallbackName") -function callback.monsterOnSpawn(monster, position) - -- custom behavior when a monster spawns -end - -callback:register() -``` - -### Npc Callback - -```lua -local callback = EventCallback("UniqueCallbackName") - -function callback.npcOnSpawn(npc, position) - -- custom behavior when a npc spawns +function callback.monsterOnDropLoot(monster, corpse) + logger.info("Monster {} has corpse {}", monster:getName(), corpse:getName()); end callback:register() diff --git a/data/scripts/eventcallbacks/creature/on_hear.lua b/data/scripts/eventcallbacks/creature/on_hear.lua deleted file mode 100644 index 2954c81c8fb..00000000000 --- a/data/scripts/eventcallbacks/creature/on_hear.lua +++ /dev/null @@ -1,5 +0,0 @@ -local callback = EventCallback("CreatureOnHearBaseEvent") - -function callback.creatureOnHear(creature, speaker, words, type) end - -callback:register() diff --git a/data/scripts/eventcallbacks/monster/on_spawn.lua b/data/scripts/eventcallbacks/monster/on_spawn.lua deleted file mode 100644 index 5a490a8edac..00000000000 --- a/data/scripts/eventcallbacks/monster/on_spawn.lua +++ /dev/null @@ -1,27 +0,0 @@ -local callback = EventCallback("MonsterOnSpawnBase") - -function callback.monsterOnSpawn(monster, position) - if not monster then - return - end - - HazardMonster.onSpawn(monster, position) - - if monster:getType():isRewardBoss() then - monster:setReward(true) - end - - if not monster:getType():canSpawn(position) then - monster:remove() - else - local spec = Game.getSpectators(position, false, false) - for _, creatureId in pairs(spec) do - local monster = Monster(creatureId) - if monster and not monster:getType():canSpawn(position) then - monster:remove() - end - end - end -end - -callback:register() diff --git a/data/scripts/globalevents/update_guild_war_status.lua b/data/scripts/globalevents/update_guild_war_status.lua new file mode 100644 index 00000000000..e499d5aa22e --- /dev/null +++ b/data/scripts/globalevents/update_guild_war_status.lua @@ -0,0 +1,10 @@ +local updateGuildWarStatus = GlobalEvent("UpdateGuildWarStatus") + +function updateGuildWarStatus.onThink(interval) + local currentTime = os.time() + db.query(string.format("UPDATE `guild_wars` SET `status` = 4, `ended` = %d WHERE `status` = 1 AND `ended` != 0 AND `ended` < %d", currentTime, currentTime)) + return true +end + +updateGuildWarStatus:interval(60000) +updateGuildWarStatus:register() diff --git a/data/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua index cfb0a6bfaaa..ed5de6421d9 100644 --- a/data/scripts/lib/register_monster_type.lua +++ b/data/scripts/lib/register_monster_type.lua @@ -194,6 +194,9 @@ registerMonsterType.flags = function(mtype, mask) end if mask.flags.rewardBoss then mtype:isRewardBoss(mask.flags.rewardBoss) + mtype.onSpawn = function(monster) + monster:setRewardBoss() + end end if mask.flags.familiar then mtype:familiar(mask.flags.familiar) diff --git a/data/scripts/lib/register_spells.lua b/data/scripts/lib/register_spells.lua index 8c549859640..f2e7cacee3d 100644 --- a/data/scripts/lib/register_spells.lua +++ b/data/scripts/lib/register_spells.lua @@ -386,7 +386,7 @@ AREA_RING1_BURST3 = { { 0, 0, 1, 1, 1, 1, 1, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 1, 1, 1, 0, 0, 0, 1, 1, 1 }, - { 1, 1, 1, 0, 3, 0, 1, 1, 1 }, + { 1, 1, 1, 0, 2, 0, 1, 1, 1 }, { 1, 1, 1, 0, 0, 0, 1, 1, 1 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 0, 1, 1, 1, 1, 1, 0, 0 }, diff --git a/data-otservbr-global/scripts/movements/others/bath_tub.lua b/data/scripts/movements/bath_tub.lua similarity index 64% rename from data-otservbr-global/scripts/movements/others/bath_tub.lua rename to data/scripts/movements/bath_tub.lua index 7ff7d1fe841..258efae4bb7 100644 --- a/data-otservbr-global/scripts/movements/others/bath_tub.lua +++ b/data/scripts/movements/bath_tub.lua @@ -1,35 +1,38 @@ -local playerBathTub = 26087 - local bathtubEnter = MoveEvent() function bathtubEnter.onStepIn(creature, item, position, fromPosition) - if not creature:isPlayer() then - return false + local player = creature:getPlayer() + if not player then + return true end local condition = Condition(CONDITION_OUTFIT) - condition:setOutfit({ lookTypeEx = playerBathTub }) + condition:setOutfit({ lookTypeEx = 26087 }) condition:setTicks(-1) position:sendMagicEffect(CONST_ME_WATERSPLASH) item:transform(BATHTUB_FILLED_NOTMOVABLE) - creature:addCondition(condition) + player:addCondition(condition) return true end +bathtubEnter:type("stepin") bathtubEnter:id(BATHTUB_FILLED) bathtubEnter:register() local bathtubExit = MoveEvent() + function bathtubExit.onStepOut(creature, item, position, fromPosition) - if not creature:isPlayer() then - return false + local player = creature:getPlayer() + if not player then + return true end item:transform(BATHTUB_FILLED) - creature:removeCondition(CONDITION_OUTFIT) + player:removeCondition(CONDITION_OUTFIT) return true end +bathtubExit:type("stepout") bathtubExit:id(BATHTUB_FILLED_NOTMOVABLE) bathtubExit:register() diff --git a/data/scripts/spells/attack/divine_grenade.lua b/data/scripts/spells/attack/divine_grenade.lua index b1dc6399c7d..488962cb2f8 100644 --- a/data/scripts/spells/attack/divine_grenade.lua +++ b/data/scripts/spells/attack/divine_grenade.lua @@ -35,7 +35,7 @@ local explodeGrenade = function(position, playerId) end local var = {} - var.instantName = "Divine Grenade Explode" + var.instantName = "Divine Grenade" var.runeName = "" var.type = 2 -- VARIANT_POSITION var.pos = position diff --git a/data/scripts/spells/attack/energy_beam.lua b/data/scripts/spells/attack/energy_beam.lua index d3be218c0ca..049470f0ecb 100644 --- a/data/scripts/spells/attack/energy_beam.lua +++ b/data/scripts/spells/attack/energy_beam.lua @@ -28,11 +28,10 @@ local spell = Spell("instant") function spell.onCastSpell(creature, var) local player = creature:getPlayer() - if creature and player and player:instantSkillWOD("Beam Mastery") then - var.runeName = "Beam Mastery" - return combatWOD:execute(creature, var) + if not creature or not player then + return false end - return combat:execute(creature, var) + return player:instantSkillWOD("Beam Mastery") and combatWOD:execute(creature, var) or combat:execute(creature, var) end spell:group("attack") diff --git a/data/scripts/spells/attack/executioners_throw.lua b/data/scripts/spells/attack/executioners_throw.lua index 2f2220625c5..08d700bfe54 100644 --- a/data/scripts/spells/attack/executioners_throw.lua +++ b/data/scripts/spells/attack/executioners_throw.lua @@ -40,28 +40,11 @@ function spell.onCastSpell(creature, var) local grade = creature:revelationStageWOD("Executioner's Throw") if grade == 0 then - creature:sendCancelMessage("You cannot cast this spell") + creature:sendCancelMessage("You need to learn this spell first") creature:getPosition():sendMagicEffect(CONST_ME_POFF) return false end - - local cooldown = 0 - if grade >= 3 then - cooldown = 10 - elseif grade >= 2 then - cooldown = 14 - elseif grade >= 1 then - cooldown = 18 - end - - var.instantName = "Executioner's Throw" - if combat:execute(creature, var) then - local condition = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 261) - condition:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition) - return true - end - return false + return combat:execute(creature, var) end spell:group("attack") @@ -75,7 +58,7 @@ spell:range(5) spell:needTarget(true) spell:blockWalls(true) spell:needWeapon(true) -spell:cooldown(1000) -- Cooldown is calculated on the casting +spell:cooldown(18 * 1000) spell:groupCooldown(2 * 1000) spell:needLearn(true) spell:vocation("knight;true", "elite knight;true") diff --git a/data/scripts/spells/attack/great_death_beam.lua b/data/scripts/spells/attack/great_death_beam.lua index 02a17c78f41..84c75132d76 100644 --- a/data/scripts/spells/attack/great_death_beam.lua +++ b/data/scripts/spells/attack/great_death_beam.lua @@ -17,6 +17,7 @@ end local combat1 = createCombat(initCombat, AREA_BEAM6) local combat2 = createCombat(initCombat, AREA_BEAM7) local combat3 = createCombat(initCombat, AREA_BEAM8) +local combat = { combat1, combat2, combat3 } local spell = Spell("instant") @@ -28,32 +29,15 @@ function spell.onCastSpell(creature, var) local grade = creature:upgradeSpellsWOD("Great Death Beam") if grade == WHEEL_GRADE_NONE then - creature:sendCancelMessage("You cannot cast this spell") + creature:sendCancelMessage("You need to learn this spell first") creature:getPosition():sendMagicEffect(CONST_ME_POFF) return false end - local cooldown = { 10, 8, 6 } - var.runeName = "Beam Mastery" - local executed = false - - local combat = { combat1, combat2, combat3 } - - executed = combat[grade]:execute(creature, var) - - if executed then - local condition = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 260) - local executedCooldown = cooldown[grade] - if executedCooldown ~= nil then - condition:setTicks((executedCooldown * 1000)) - end - creature:addCondition(condition) - return true - end - return false + return combat[grade]:execute(creature, var) end -spell:group("attack") +spell:group("attack", "greatbeams") spell:id(260) spell:name("Great Death Beam") spell:words("exevo max mort") @@ -62,8 +46,8 @@ spell:mana(140) spell:isPremium(false) spell:needDirection(true) spell:blockWalls(true) -spell:cooldown(1000) -- Cooldown is calculated on the casting -spell:groupCooldown(2 * 1000) +spell:cooldown(10 * 1000) +spell:groupCooldown(2 * 1000, 6 * 1000) spell:needLearn(true) spell:vocation("sorcerer;true", "master sorcerer;true") spell:register() diff --git a/data/scripts/spells/attack/great_energy_beam.lua b/data/scripts/spells/attack/great_energy_beam.lua index aae93e95c9a..f6b61f19fa4 100644 --- a/data/scripts/spells/attack/great_energy_beam.lua +++ b/data/scripts/spells/attack/great_energy_beam.lua @@ -28,15 +28,13 @@ local spell = Spell("instant") function spell.onCastSpell(creature, var) local player = creature:getPlayer() - if creature and player and player:instantSkillWOD("Beam Mastery") then - var.runeName = "Beam Mastery" - return combatWOD:execute(creature, var) + if not creature or not player then + return false end - - return combat:execute(creature, var) + return player:instantSkillWOD("Beam Mastery") and combatWOD:execute(creature, var) or combat:execute(creature, var) end -spell:group("attack") +spell:group("attack", "greatbeams") spell:id(23) spell:name("Great Energy Beam") spell:words("exevo gran vis lux") @@ -47,7 +45,7 @@ spell:isPremium(false) spell:needDirection(true) spell:blockWalls(true) spell:cooldown(6 * 1000) -spell:groupCooldown(2 * 1000) +spell:groupCooldown(2 * 1000, 6 * 1000) spell:needLearn(false) spell:vocation("sorcerer;true", "master sorcerer;true") spell:register() diff --git a/data/scripts/spells/attack/ice_burst.lua b/data/scripts/spells/attack/ice_burst.lua index 9e1560f9dc9..fedcd9d5a04 100644 --- a/data/scripts/spells/attack/ice_burst.lua +++ b/data/scripts/spells/attack/ice_burst.lua @@ -14,50 +14,27 @@ combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") local spell = Spell("instant") function spell.onCastSpell(creature, var) - if not creature or not creature:isPlayer() then - return false - end - local grade = creature:revelationStageWOD("Twin Burst") if grade == 0 then - creature:sendCancelMessage("You cannot cast this spell") + creature:sendCancelMessage("You need to learn this spell first") creature:getPosition():sendMagicEffect(CONST_ME_POFF) return false end - local cooldown = 0 - if grade >= 3 then - cooldown = 14 - elseif grade >= 2 then - cooldown = 18 - elseif grade >= 1 then - cooldown = 22 - end - - var.instantName = "Twin Burst" - if combat:execute(creature, var) then - -- Ice cooldown - local condition1 = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 262) - condition1:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition1) - -- Earth cooldown - local condition2 = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 263) - condition2:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition2) - return true - end - return false + return combat:execute(creature, var) end -spell:group("attack") +spell:group("attack", "burstsofnature") spell:id(262) spell:name("Ice Burst") spell:words("exevo ulus frigo") +spell:castSound(SOUND_EFFECT_TYPE_SPELL_ETERNAL_WINTER) spell:level(300) spell:mana(230) spell:isPremium(true) -spell:cooldown(1000) -- Cooldown is calculated on the casting -spell:groupCooldown(2 * 1000) +spell:isSelfTarget(true) +spell:cooldown(22 * 1000) +spell:groupCooldown(2 * 1000, 22 * 1000) spell:needLearn(true) spell:vocation("druid;true", "elder druid;true") spell:register() diff --git a/data/scripts/spells/attack/terra_burst.lua b/data/scripts/spells/attack/terra_burst.lua index 8a805c0ba48..15ce35c4912 100644 --- a/data/scripts/spells/attack/terra_burst.lua +++ b/data/scripts/spells/attack/terra_burst.lua @@ -14,50 +14,27 @@ combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") local spell = Spell("instant") function spell.onCastSpell(creature, var) - if not creature or not creature:isPlayer() then - return false - end - local grade = creature:revelationStageWOD("Twin Burst") if grade == 0 then - creature:sendCancelMessage("You cannot cast this spell") + creature:sendCancelMessage("You need to learn this spell first") creature:getPosition():sendMagicEffect(CONST_ME_POFF) return false end - local cooldown = 0 - if grade >= 3 then - cooldown = 14 - elseif grade >= 2 then - cooldown = 18 - elseif grade >= 1 then - cooldown = 22 - end - - var.instantName = "Twin Burst" - if combat:execute(creature, var) then - -- Ice cooldown - local condition1 = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 262) - condition1:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition1) - -- Earth cooldown - local condition2 = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 263) - condition2:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition2) - return true - end - return false + return combat:execute(creature, var) end -spell:group("attack") +spell:group("attack", "burstsofnature") spell:id(263) spell:name("Terra Burst") spell:words("exevo ulus tera") +spell:castSound(SOUND_EFFECT_TYPE_SPELL_WRATH_OF_NATURE) spell:level(300) spell:mana(230) spell:isPremium(true) -spell:cooldown(1000) -- Cooldown is calculated on the casting -spell:groupCooldown(2 * 1000) +spell:isSelfTarget(true) +spell:cooldown(22 * 1000) +spell:groupCooldown(2 * 1000, 22 * 1000) spell:needLearn(true) spell:vocation("druid;true", "elder druid;true") spell:register() diff --git a/data/scripts/spells/support/divine_empowerment.lua b/data/scripts/spells/support/divine_empowerment.lua index e05203359f8..248f01a6e0f 100644 --- a/data/scripts/spells/support/divine_empowerment.lua +++ b/data/scripts/spells/support/divine_empowerment.lua @@ -26,18 +26,6 @@ function spell.onCastSpell(creature, var) return false end - local cooldown = 0 - if grade >= 3 then - cooldown = 24 - elseif grade >= 2 then - cooldown = 28 - elseif grade >= 1 then - cooldown = 32 - end - local condition = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 268) - condition:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) - creature:addCondition(condition) - local position = creature:getPosition() for x = -1, 1 do for y = -1, 1 do @@ -63,7 +51,7 @@ spell:isPremium(true) spell:range(7) spell:isSelfTarget(true) spell:isAggressive(false) -spell:cooldown(1000) -- Cooldown is calculated on the casting +spell:cooldown(32 * 1000) spell:groupCooldown(2 * 1000) spell:needLearn(true) spell:vocation("paladin;true", "royal paladin;true") diff --git a/data/scripts/spells/support/sharpshooter.lua b/data/scripts/spells/support/sharpshooter.lua index 568fec86e00..e5111781562 100644 --- a/data/scripts/spells/support/sharpshooter.lua +++ b/data/scripts/spells/support/sharpshooter.lua @@ -4,9 +4,9 @@ local combat = Combat() combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -local speed = Condition(CONDITION_HASTE) +local speed = Condition(CONDITION_PARALYZE) speed:setParameter(CONDITION_PARAM_TICKS, spellDuration) -speed:setFormula(0.7, 0, 0.7, 0) +speed:setFormula(0.7, 56, 0.7, 56) combat:addCondition(speed) local exhaustHealGroup = Condition(CONDITION_SPELLGROUPCOOLDOWN) diff --git a/data/scripts/systems/item_tiers.lua b/data/scripts/systems/item_tiers.lua index 06a8321a034..cc7a2a2697d 100644 --- a/data/scripts/systems/item_tiers.lua +++ b/data/scripts/systems/item_tiers.lua @@ -90,7 +90,7 @@ local itemTierClassifications = { }, } --- Item tier with gold price for uprading it +-- Item tier with gold price for upgrading it for classificationId, classificationTable in ipairs(itemTierClassifications) do local itemClassification = Game.createItemClassification(classificationId) local classification = {} diff --git a/data/scripts/talkactions/gm/ban.lua b/data/scripts/talkactions/gm/ban.lua index 0ab07040333..4d7569c78f5 100644 --- a/data/scripts/talkactions/gm/ban.lua +++ b/data/scripts/talkactions/gm/ban.lua @@ -1,48 +1,48 @@ -local banDays = 7 - local ban = TalkAction("/ban") function ban.onSay(player, words, param) -- create log logCommand(player, words, param) - if param == "" then - player:sendCancelMessage("Command param required.") + local params = param:split(",") + if #params < 3 then + player:sendCancelMessage("Command requires 3 parameters: /ban , , ") return true end - local name = param - local reason = "" + local playerName = params[1]:trim() + local banDuration = tonumber(params[2]:trim()) + local banReason = params[3]:trim() - local separatorPos = param:find(",") - if separatorPos then - name = param:sub(0, separatorPos - 1) - reason = string.trim(param:sub(separatorPos + 1)) + if not banDuration or banDuration <= 0 then + player:sendCancelMessage("Ban duration must be a positive number.") + return true end - local accountId = getAccountNumberByPlayerName(name) + local accountId = Game.getPlayerAccountId(playerName) if accountId == 0 then return true end local resultId = db.storeQuery("SELECT 1 FROM `account_bans` WHERE `account_id` = " .. accountId) - if resultId ~= false then - Result.free(resultId) + if resultId then + result.free(resultId) return true end - local timeNow = os.time() - db.query("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" .. accountId .. ", " .. db.escapeString(reason) .. ", " .. timeNow .. ", " .. timeNow + (banDays * 86400) .. ", " .. player:getGuid() .. ")") + local currentTime = os.time() + local expirationTime = currentTime + (banDuration * 24 * 60 * 60) + db.query(string.format("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (%d, %s, %d, %d, %d)", accountId, db.escapeString(banReason), currentTime, expirationTime, player:getGuid())) - local target = Player(name) + local target = Player(playerName) if target then - local text = target:getName() .. " has been banned" - player:sendTextMessage(MESSAGE_ADMINISTRATOR, text) - Webhook.sendMessage("Player Banned", text .. " reason: " .. reason .. ". (by: " .. player:getName() .. ")", WEBHOOK_COLOR_YELLOW, announcementChannels["serverAnnouncements"]) + player:sendTextMessage(MESSAGE_ADMINISTRATOR, string.format("%s has been banned for %d days.", target:getName(), banDuration)) target:remove() + Webhook.sendMessage("Player Banned", string.format("%s has been banned for %d days. Reason: %s (by: %s)", target:getName(), banDuration, banReason, player:getName()), WEBHOOK_COLOR_YELLOW, announcementChannels["serverAnnouncements"]) else - player:sendTextMessage(MESSAGE_ADMINISTRATOR, name .. " has been banned.") + player:sendTextMessage(MESSAGE_ADMINISTRATOR, string.format("%s has been banned for %d days.", playerName, banDuration)) end + return true end ban:separator(" ") diff --git a/data/scripts/talkactions/gm/bless_status.lua b/data/scripts/talkactions/gm/bless_status.lua index 7cb861947dd..a316330db31 100644 --- a/data/scripts/talkactions/gm/bless_status.lua +++ b/data/scripts/talkactions/gm/bless_status.lua @@ -1,4 +1,4 @@ -dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/blessing.lua") local blessStatus = TalkAction("/bless") @@ -6,7 +6,7 @@ function blessStatus.onSay(player, words, param) -- create log logCommand(player, words, param) - Blessings.sendBlessStatus(player) + player:sendBlessStatus() return true end diff --git a/data/scripts/talkactions/gm/gold_highscore.lua b/data/scripts/talkactions/gm/gold_highscore.lua index de923712887..a68df6900a5 100644 --- a/data/scripts/talkactions/gm/gold_highscore.lua +++ b/data/scripts/talkactions/gm/gold_highscore.lua @@ -1,28 +1,33 @@ -local gold_rank = TalkAction("/goldrank") +local goldRank = TalkAction("/goldrank") -function gold_rank.onSay(player, words, param) +function goldRank.onSay(player, words, param) -- create log logCommand(player, words, param) - local resultId = db.storeQuery("SELECT `balance`, `name` FROM `players` WHERE group_id < 3 ORDER BY balance DESC LIMIT 10") - if resultId ~= false then - local str = "" - local x = 0 - repeat - x = x + 1 - str = str .. "\n" .. x .. "- " .. Result.getString(resultId, "name") .. " (" .. Result.getNumber(resultId, "balance") .. ")." - until not Result.next(resultId) - Result.free(resultId) - if str == "" then - str = "No highscore to show." - end - player:popupFYI("Current gold highscore for this server:\n" .. str) - else + local highscoreQuery = db.storeQuery("SELECT `balance`, `name` FROM `players` WHERE group_id < 3 ORDER BY balance DESC LIMIT 10") + if not highscoreQuery then player:sendCancelMessage("No highscore to show.") + return true end + + local highscoreList = "" + local rank = 0 + repeat + rank = rank + 1 + local playerName = Result.getString(highscoreQuery, "name") + local playerBalance = FormatNumber(Result.getNumber(highscoreQuery, "balance")) + highscoreList = highscoreList .. "\n" .. rank .. "- " .. playerName .. " (" .. playerBalance .. ")." + until not Result.next(highscoreQuery) + + Result.free(highscoreQuery) + if highscoreList == "" then + highscoreList = "No highscore to show." + end + + player:popupFYI("Current gold highscore for this server:\n" .. highscoreList) return true end -gold_rank:separator(" ") -gold_rank:groupType("gamemaster") -gold_rank:register() +goldRank:separator(" ") +goldRank:groupType("gamemaster") +goldRank:register() diff --git a/data/scripts/talkactions/god/add_addon.lua b/data/scripts/talkactions/god/add_addon.lua index 026336e270e..bbcd21c94fa 100644 --- a/data/scripts/talkactions/god/add_addon.lua +++ b/data/scripts/talkactions/god/add_addon.lua @@ -1,45 +1,305 @@ -local addons = TalkAction("/addaddon") +local addaddon = TalkAction("/addaddon") -function addons.onSay(player, words, param) - -- create log - logCommand(player, words, param) +local looktypes = { + -- Female Outfits + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 147, + 148, + 149, + 150, + 155, + 156, + 157, + 158, + 252, + 269, + 270, + 279, + 288, + 324, + 329, + 336, + 366, + 431, + 433, + 464, + 466, + 471, + 513, + 514, + 542, + 575, + 578, + 618, + 620, + 632, + 635, + 636, + 664, + 666, + 683, + 694, + 696, + 698, + 724, + 732, + 745, + 749, + 759, + 845, + 852, + 874, + 885, + 900, + 909, + 929, + 956, + 958, + 963, + 965, + 967, + 969, + 971, + 973, + 975, + 1020, + 1024, + 1043, + 1050, + 1057, + 1070, + 1095, + 1103, + 1128, + 1147, + 1162, + 1174, + 1187, + 1203, + 1205, + 1207, + 1211, + 1244, + 1246, + 1252, + 1271, + 1280, + 1283, + 1289, + 1293, + 1323, + 1332, + 1339, + 1372, + 1383, + 1385, + 1387, + 1416, + 1437, + 1445, + 1450, + 1456, + 1461, + 1490, + 1501, + 1569, + 1576, + 1582, + 1598, + 1613, + 1619, + 1663, + 1676, + 1681, - local target - local split = param:split(",") - local name = split[1] + -- Male Outfits + 1714, + 1723, + 1726, + 1746, + 1775, + 1777, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 143, + 144, + 145, + 146, + 151, + 152, + 153, + 154, + 251, + 268, + 273, + 278, + 289, + 325, + 328, + 335, + 367, + 430, + 432, + 463, + 465, + 472, + 512, + 516, + 541, + 574, + 577, + 610, + 619, + 633, + 634, + 637, + 665, + 667, + 684, + 695, + 697, + 699, + 725, + 733, + 746, + 750, + 760, + 846, + 853, + 873, + 884, + 899, + 908, + 931, + 955, + 957, + 962, + 964, + 966, + 968, + 970, + 972, + 974, + 1021, + 1023, + 1042, + 1051, + 1056, + 1069, + 1094, + 1102, + 1127, + 1146, + 1161, + 1173, + 1186, + 1202, + 1204, + 1206, + 1210, + 1243, + 1245, + 1251, + 1270, + 1279, + 1282, + 1288, + 1292, + 1322, + 1331, + 1338, + 1371, + 1382, + 1384, + 1386, + 1415, + 1436, + 1444, + 1449, + 1457, + 1460, + 1489, + 1500, + 1568, + 1575, + 1581, + 1597, + 1612, + 1618, + 1662, + 1675, + 1680, + 1713, + 1722, + 1725, + 1745, + 1774, + 1776, +} + +function addaddon.onSay(player, words, param) + -- Create log + logCommand(player, words, param) if param == "" then - target = player:getTarget() - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Gives players the ability to wear addon for a specific outfit. Usage: /addaddon , ") - return true - end - else - target = Player(name) + player:sendCancelMessage("Command param required.") + return true end - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Player " .. name .. " is currently not online.") + local split = param:split(",") + if #split < 3 then + player:sendCancelMessage("Usage: /addaddon , , ") return true end - local looktype = tonumber(split[2]) - if not looktype then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Invalid looktype.") + local playerName = split[1] + local target = Player(playerName) + + if not target then + player:sendCancelMessage("Player not found.") return true end - local addons = tonumber(split[3]) - if not addons or addons < 0 or addons > 3 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Invalid addon.") + local addonParam = string.trim(split[2]) + local addonValue = tonumber(string.trim(split[3])) + + if not addonValue or addonValue < 0 or addonValue > 3 then + player:sendCancelMessage("Invalid addon value. It should be between 0 and 3.") return true end - target:addOutfitAddon(looktype, addons) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Addon for looktype " .. looktype .. "a for " .. target:getName() .. " set to " .. addons .. ".") + if addonParam == "all" then + for _, looktype in ipairs(looktypes) do + target:addOutfitAddon(looktype, addonValue) + end + + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added addon %d to all your looktypes.", player:getName(), addonValue)) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added addon %d to all looktypes of player %s.", addonValue, target:getName())) + else + local looktype = tonumber(addonParam) + if not looktype then + player:sendCancelMessage("Invalid looktype.") + return true + end + + target:addOutfitAddon(looktype, addonValue) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("Addon %d for looktype %d set for player %s.", addonValue, looktype, target:getName())) + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added addon %d for looktype %d to you.", player:getName(), addonValue, looktype)) + end return true end -addons:separator(" ") -addons:groupType("god") -addons:register() +addaddon:separator(" ") +addaddon:groupType("god") +addaddon:register() diff --git a/data/scripts/talkactions/god/add_addons.lua b/data/scripts/talkactions/god/add_addons.lua deleted file mode 100644 index 5498ae1e11b..00000000000 --- a/data/scripts/talkactions/god/add_addons.lua +++ /dev/null @@ -1,277 +0,0 @@ --- /addaddons playername - -local addons = TalkAction("/addaddons") -local looktypes = { - - -- Female Outfits - 136, - 137, - 138, - 139, - 140, - 141, - 142, - 147, - 148, - 149, - 150, - 155, - 156, - 157, - 158, - 252, - 269, - 270, - 279, - 288, - 324, - 329, - 336, - 366, - 431, - 433, - 464, - 466, - 471, - 513, - 514, - 542, - 575, - 578, - 618, - 620, - 632, - 635, - 636, - 664, - 666, - 683, - 694, - 696, - 698, - 724, - 732, - 745, - 749, - 759, - 845, - 852, - 874, - 885, - 900, - 909, - 929, - 956, - 958, - 963, - 965, - 967, - 969, - 971, - 973, - 975, - 1020, - 1024, - 1043, - 1050, - 1057, - 1070, - 1095, - 1103, - 1128, - 1147, - 1162, - 1174, - 1187, - 1203, - 1205, - 1207, - 1211, - 1244, - 1246, - 1252, - 1271, - 1280, - 1283, - 1289, - 1293, - 1323, - 1332, - 1339, - 1372, - 1383, - 1385, - 1387, - 1416, - 1437, - 1445, - 1450, - 1456, - 1461, - 1490, - 1501, - 1569, - 1576, - 1582, - 1598, - 1613, - 1619, - 1663, - 1676, - 1681, - - -- Male Outfits - 128, - 129, - 130, - 131, - 132, - 133, - 134, - 143, - 144, - 145, - 146, - 151, - 152, - 153, - 154, - 251, - 268, - 273, - 278, - 289, - 325, - 328, - 335, - 367, - 430, - 432, - 463, - 465, - 472, - 512, - 516, - 541, - 574, - 577, - 610, - 619, - 633, - 634, - 637, - 665, - 667, - 684, - 695, - 697, - 699, - 725, - 733, - 746, - 750, - 760, - 846, - 853, - 873, - 884, - 899, - 908, - 931, - 955, - 957, - 962, - 964, - 966, - 968, - 970, - 972, - 974, - 1021, - 1023, - 1042, - 1051, - 1056, - 1069, - 1094, - 1102, - 1127, - 1146, - 1161, - 1173, - 1186, - 1202, - 1204, - 1206, - 1210, - 1243, - 1245, - 1251, - 1270, - 1279, - 1282, - 1288, - 1292, - 1322, - 1331, - 1338, - 1371, - 1382, - 1384, - 1386, - 1415, - 1436, - 1444, - 1449, - 1457, - 1460, - 1489, - 1500, - 1568, - 1575, - 1581, - 1597, - 1612, - 1618, - 1662, - 1675, - 1680, -} - -function addons.onSay(player, words, param) - -- create log - logCommand(player, words, param) - - local target - if param == "" then - target = player:getTarget() - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Gives players the ability to wear all addons. Usage: /addaddons ") - return true - end - else - target = Player(param) - end - - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Player " .. param .. " is currently not online.") - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Cannot perform action.") - return true - end - - for i = 1, #looktypes do - target:addOutfitAddon(looktypes[i], 3) - end - - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "All addons unlocked for " .. target:getName() .. ".") - target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "All of your addons have been unlocked!") - return true -end - -addons:separator(" ") -addons:groupType("god") -addons:register() diff --git a/data/scripts/talkactions/god/add_mount.lua b/data/scripts/talkactions/god/add_mount.lua index b8b2f00dda1..5dc8c9a97fb 100644 --- a/data/scripts/talkactions/god/add_mount.lua +++ b/data/scripts/talkactions/god/add_mount.lua @@ -1,13 +1,7 @@ ---[[ - /addmount playername, mount -]] +local addmount = TalkAction("/addmount") -local printConsole = true - -local addOutfit = TalkAction("/addmount") - -function addOutfit.onSay(player, words, param) - -- create log +function addmount.onSay(player, words, param) + -- Create log logCommand(player, words, param) if param == "" then @@ -16,23 +10,41 @@ function addOutfit.onSay(player, words, param) end local split = param:split(",") - local name = split[1] - - local target = Player(name) - if target then - local mount = tonumber(split[2]) - target:addMount(mount) - target:sendTextMessage(MESSAGE_ADMINISTRATOR, "" .. player:getName() .. " has been added a new mount for you.") - player:sendTextMessage(MESSAGE_ADMINISTRATOR, "You have sucessfull added mount " .. mount .. " to the player " .. target:getName() .. ".") - if printConsole then - logger.info("[addOutfit.onSay] - Player: {} has been added mount: {} to the player: {}", player:getName(), lookType, target:getName()) - end + if #split < 2 then + player:sendCancelMessage("Usage: /addmount , ") + return true + end + + local playerName = split[1] + local target = Player(playerName) + + if not target then + player:sendCancelMessage("Player not found.") return true end - player:sendCancelMessage("Player not found.") + + local mountParam = string.trim(split[2]) + if mountParam == "all" then + for mountId = 1, 231 do + target:addMount(mountId) + end + + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added all mounts to you.", player:getName())) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added all mounts to player %s.", target:getName())) + else + local mountId = tonumber(mountParam) + if not mountId then + player:sendCancelMessage("Invalid mount ID.") + return true + end + + target:addMount(mountId) + target:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added a new mount for you.", player:getName())) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added mount %d to player %s.", mountId, target:getName())) + end return true end -addOutfit:separator(" ") -addOutfit:groupType("god") -addOutfit:register() +addmount:separator(" ") +addmount:groupType("god") +addmount:register() diff --git a/data/scripts/talkactions/god/add_mounts.lua b/data/scripts/talkactions/god/add_mounts.lua deleted file mode 100644 index 3de09916505..00000000000 --- a/data/scripts/talkactions/god/add_mounts.lua +++ /dev/null @@ -1,32 +0,0 @@ --- /addmounts playername - -local mounts = TalkAction("/addmounts") -function mounts.onSay(player, words, param) - local target - if param == "" then - target = player:getTarget() - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Unlocks all mounts for certain player. Usage: /mounts ") - return true - end - else - target = Player(param) - end - - if not target then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Player " .. param .. " is not currently online.") - return true - end - - for i = 1, 221 do - target:addMount(i) - end - - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "All mounts unlocked for: " .. target:getName()) - target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "All of your mounts have been unlocked!") - return true -end - -mounts:separator(" ") -mounts:groupType("god") -mounts:register() diff --git a/data/scripts/talkactions/god/add_outfit.lua b/data/scripts/talkactions/god/add_outfit.lua deleted file mode 100644 index a27fb4f8a18..00000000000 --- a/data/scripts/talkactions/god/add_outfit.lua +++ /dev/null @@ -1,42 +0,0 @@ ---[[ - /addoutfit playername, looktype - make sure you’re adding a male outfit to a male character - if you try to add a female outfit to a male character, it won’t work -]] - -local printConsole = true - -local addOutfit = TalkAction("/addoutfit") - -function addOutfit.onSay(player, words, param) - -- create log - logCommand(player, words, param) - - if param == "" then - player:sendCancelMessage("Command param required.") - return true - end - - local split = param:split(",") - local name = split[1] - - local target = Player(name) - if target then - local lookType = tonumber(split[2]) - target:addOutfit(lookType) - target:sendTextMessage(MESSAGE_ADMINISTRATOR, "" .. player:getName() .. " has been added a new outfit for you.") - player:sendTextMessage(MESSAGE_ADMINISTRATOR, "You have sucessfull added looktype " .. lookType .. " to the player " .. target:getName() .. ".") - if printConsole then - logger.info("[addOutfit.onSay] - Player: {} has been added looktype: {} to the player: {}", player:getName(), lookType, target:getName()) - end - return true - else - player:sendCancelMessage("Player not found.") - return true - end - return true -end - -addOutfit:separator(" ") -addOutfit:groupType("god") -addOutfit:register() diff --git a/data/scripts/talkactions/god/add_skill.lua b/data/scripts/talkactions/god/add_skill.lua index 09d240ece4d..3d082f656af 100644 --- a/data/scripts/talkactions/god/add_skill.lua +++ b/data/scripts/talkactions/god/add_skill.lua @@ -1,25 +1,20 @@ +local skillMap = { + club = SKILL_CLUB, + sword = SKILL_SWORD, + axe = SKILL_AXE, + dist = SKILL_DISTANCE, + shield = SKILL_SHIELD, + fish = SKILL_FISHING, +} + local function getSkillId(skillName) - if skillName == "club" then - return SKILL_CLUB - elseif skillName == "sword" then - return SKILL_SWORD - elseif skillName == "axe" then - return SKILL_AXE - elseif skillName:sub(1, 4) == "dist" then - return SKILL_DISTANCE - elseif skillName:sub(1, 6) == "shield" then - return SKILL_SHIELD - elseif skillName:sub(1, 4) == "fish" then - return SKILL_FISHING - else - return SKILL_FIST - end + return skillMap[skillName:match("^%a+")] or SKILL_FIST end local addSkill = TalkAction("/addskill") function addSkill.onSay(player, words, param) - -- create log + -- Create log logCommand(player, words, param) if param == "" then @@ -28,39 +23,51 @@ function addSkill.onSay(player, words, param) end local split = param:split(",") - if not split[2] then - player:sendCancelMessage("Insufficient parameters.") + if #split < 2 then + player:sendCancelMessage("Usage: /addskill , , [amount]") return true end - local target = Player(split[1]) - if not target then - player:sendCancelMessage("A player with that name is not online.") + local targetPlayerName = split[1]:trim() + local targetPlayer = Player(targetPlayerName) + + if not targetPlayer then + player:sendCancelMessage("Player not found.") return true end - split[2] = split[2]:trimSpace() + local skillParam = split[2]:trim() + local skillIncreaseAmount = tonumber(split[3]) or 1 + local skillPrefix = skillParam:sub(1, 1) - local count = 1 - if split[3] then - count = tonumber(split[3]) - end + if skillPrefix == "l" then + local targetNewLevel = targetPlayer:getLevel() + skillIncreaseAmount + local targetNewExp = Game.getExperienceForLevel(targetNewLevel) + local experienceToAdd = targetNewExp - targetPlayer:getExperience() + local levelText = (skillIncreaseAmount > 1) and "levels" or "level" - local ch = split[2]:sub(1, 1) - if ch == "l" or ch == "e" then - targetLevel = target:getLevel() + count - targetExp = Game.getExperienceForLevel(targetLevel) - addExp = targetExp - target:getExperience() - target:addExperience(addExp, false) - elseif ch == "m" then - for i = 1, count do - target:addManaSpent(target:getVocation():getRequiredManaSpent(target:getBaseMagicLevel() + 1) - target:getManaSpent(), true) + targetPlayer:addExperience(experienceToAdd, false) + targetPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added %d %s to you.", player:getName(), skillIncreaseAmount, levelText)) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added %d %s to player %s.", skillIncreaseAmount, levelText, targetPlayer:getName())) + elseif skillPrefix == "m" then + for _ = 1, skillIncreaseAmount do + local requiredManaSpent = targetPlayer:getVocation():getRequiredManaSpent(targetPlayer:getBaseMagicLevel() + 1) + targetPlayer:addManaSpent(requiredManaSpent - targetPlayer:getManaSpent(), true) end + + local magicText = (skillIncreaseAmount > 1) and "magic levels" or "magic level" + targetPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added %d %s to you.", player:getName(), skillIncreaseAmount, magicText)) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added %d %s to player %s.", skillIncreaseAmount, magicText, targetPlayer:getName())) else - local skillId = getSkillId(split[2]) - for i = 1, count do - target:addSkillTries(skillId, target:getVocation():getRequiredSkillTries(skillId, target:getSkillLevel(skillId) + 1) - target:getSkillTries(skillId), true) + local skillId = getSkillId(skillParam) + for _ = 1, skillIncreaseAmount do + local requiredSkillTries = targetPlayer:getVocation():getRequiredSkillTries(skillId, targetPlayer:getSkillLevel(skillId) + 1) + targetPlayer:addSkillTries(skillId, requiredSkillTries - targetPlayer:getSkillTries(skillId), true) end + + local skillText = (skillIncreaseAmount > 1) and "skill levels" or "skill level" + targetPlayer:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("%s has added %d %s %s to you.", player:getName(), skillIncreaseAmount, skillParam, skillText)) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have successfully added %d %s %s to player %s.", skillIncreaseAmount, skillParam, skillText, targetPlayer:getName())) end return true end diff --git a/data/scripts/talkactions/god/manage_monster.lua b/data/scripts/talkactions/god/manage_monster.lua index da110d59265..106acefa078 100644 --- a/data/scripts/talkactions/god/manage_monster.lua +++ b/data/scripts/talkactions/god/manage_monster.lua @@ -1,37 +1,38 @@ -local function createCreaturesAround(player, maxRadius, creatureName, creatureCount, creatureForge, boolForceCreate) - local position = player:getPosition() - local createdCount = 0 +local function createCreaturesAround(player, maxRadius, creatureName, creatureCount, creatureForge, forceCreateMonsters) + local playerPosition = player:getPosition() + local createdCreatureCount = 0 local sendMessage = false local canSetFiendish, canSetInfluenced, influencedLevel = CheckDustLevel(creatureForge, player) + for radius = 1, maxRadius do - if createdCount >= creatureCount then + if createdCreatureCount >= creatureCount then break end - local minX = position.x - radius - local maxX = position.x + radius - local minY = position.y - radius - local maxY = position.y + radius + local minX, maxX = playerPosition.x - radius, playerPosition.x + radius + local minY, maxY = playerPosition.y - radius, playerPosition.y + radius for dx = minX, maxX do for dy = minY, maxY do - if (dx == minX or dx == maxX or dy == minY or dy == maxY) and createdCount < creatureCount then - local checkPosition = Position(dx, dy, position.z) + if (dx == minX or dx == maxX or dy == minY or dy == maxY) and createdCreatureCount < creatureCount then + local checkPosition = Position(dx, dy, playerPosition.z) local tile = Tile(checkPosition) if tile and not tile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) then - local monster = Game.createMonster(creatureName, checkPosition, false, boolForceCreate) + local monster = Game.createMonster(creatureName, checkPosition, false, forceCreateMonsters) if monster then - createdCount = createdCount + 1 + createdCreatureCount = createdCreatureCount + 1 monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - position:sendMagicEffect(CONST_ME_MAGIC_RED) - if creatureForge ~= nil and monster:isForgeable() then + playerPosition:sendMagicEffect(CONST_ME_MAGIC_RED) + + if creatureForge and monster:isForgeable() then local monsterType = monster:getType() if canSetFiendish then - SetFiendish(monsterType, position, player, monster) + SetFiendish(monsterType, playerPosition, player, monster) end + if canSetInfluenced then SetInfluenced(monsterType, monster, player, influencedLevel) end - elseif notSendMessage then + elseif not sendMessage then sendMessage = true end end @@ -40,86 +41,58 @@ local function createCreaturesAround(player, maxRadius, creatureName, creatureCo end end end - if sendMessage == true then + + if sendMessage then player:sendCancelMessage("Only allowed monsters can be fiendish or influenced.") end - - logger.info("Player {} created '{}' monsters", player:getName(), createdCount) end local createMonster = TalkAction("/m") --- @function createMonster.onSay --- @desc TalkAction to create monsters with multiple options. --- @param player: The player executing the command. --- @param words: Command words. --- @param param: String containing the command parameters. --- Format: "/m monstername, monstercount, [fiendish/influenced level], spawnRadius, [forceCreate]" --- Example: "/m rat, 10, fiendish, 5, true" --- @param: the last param is by default "false", if add "," or any value it's set to true --- @return true if the command is executed successfully, false otherwise. function createMonster.onSay(player, words, param) -- create log logCommand(player, words, param) + if param == "" then player:sendCancelMessage("Monster name param required.") - logger.error("[createMonster.onSay] - Monster name param not found.") return true end - local position = player:getPosition() - - local split = param:split(",") - local monsterName = split[1] - local monsterCount = 0 - if split[2] then - split[2] = split[2]:trimSpace() - monsterCount = tonumber(split[2]) - end - - local monsterForge = nil - if split[3] then - split[3] = split[3]:trimSpace() - monsterForge = split[3] - end + local playerPosition = player:getPosition() + local splitParams = param:split(",") + local monsterName = splitParams[1] + local monsterCount = tonumber(splitParams[2] or 1) + local monsterForge = splitParams[3] and splitParams[3]:trimSpace() or nil + local spawnRadius = tonumber(splitParams[4] or 5) + local forceCreate = splitParams[5] and true or false if monsterCount > 1 then - local spawnRadius = 5 - if split[4] then - split[4] = split[4]:trimSpace() - spawnRadius = split[4] - print(spawnRadius) - end - - local forceCreate = false - if split[5] then - forceCreate = true - end - createCreaturesAround(player, spawnRadius, monsterName, monsterCount, monsterForge, forceCreate) return true end - local monster = Game.createMonster(monsterName, position) + local monster = Game.createMonster(monsterName, playerPosition) if monster then local canSetFiendish, canSetInfluenced, influencedLevel = CheckDustLevel(monsterForge, player) monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - position:sendMagicEffect(CONST_ME_MAGIC_RED) - if monsterForge ~= nil and not monster:isForgeable() then + playerPosition:sendMagicEffect(CONST_ME_MAGIC_RED) + + if monsterForge and not monster:isForgeable() then player:sendCancelMessage("Only allowed monsters can be fiendish or influenced.") return true end local monsterType = monster:getType() if canSetFiendish then - SetFiendish(monsterType, position, player, monster) + SetFiendish(monsterType, playerPosition, player, monster) end + if canSetInfluenced then SetInfluenced(monsterType, monster, player, influencedLevel) end else player:sendCancelMessage("There is not enough room.") - position:sendMagicEffect(CONST_ME_POFF) + playerPosition:sendMagicEffect(CONST_ME_POFF) end return true end @@ -128,29 +101,27 @@ createMonster:separator(" ") createMonster:groupType("god") createMonster:register() ------------------ Rename monster name ----------------- local setMonsterName = TalkAction("/setmonstername") --- @function setMonsterName.onSay --- @desc TalkAction to rename nearby monsters within a radius of 4 sqm. --- Format: "/setmonstername newName" function setMonsterName.onSay(player, words, param) + -- create log + logCommand(player, words, param) + if param == "" then player:sendCancelMessage("Command param required.") return true end - local split = param:split(",") - local monsterNewName = split[1] - + local splitParams = param:split(",") + local newMonsterName = splitParams[1] local spectators, spectator = Game.getSpectators(player:getPosition(), false, false, 4, 4, 4, 4) + for i = 1, #spectators do spectator = spectators[i] if spectator:isMonster() then - spectator:setName(monsterNewName) + spectator:setName(newMonsterName) end end - return true end diff --git a/data/scripts/talkactions/player/vip.lua b/data/scripts/talkactions/player/vip.lua index 65ca4be99f8..a80f6dd54dc 100644 --- a/data/scripts/talkactions/player/vip.lua +++ b/data/scripts/talkactions/player/vip.lua @@ -1,12 +1,10 @@ local vip = TalkAction("!checkvip", "!vip") function vip.onSay(player, words, param) - if not player:isVip() then - local msg = "You do not have VIP on your account." - player:sendCancelMessage(msg) - player:sendTextMessage(MESSAGE_STATUS, msg) + if player:isVip() then + player:sendVipStatus() else - CheckPremiumAndPrint(player, MESSAGE_STATUS) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You do not have VIP on your account.") end return true end diff --git a/docker/Dockerfile.arm b/docker/Dockerfile.arm index ef159ba142f..2fca1b525a0 100644 --- a/docker/Dockerfile.arm +++ b/docker/Dockerfile.arm @@ -1,5 +1,5 @@ # Stage 1: Download all dependencies -FROM ubuntu:23.04 AS dependencies +FROM ubuntu:24.04 AS dependencies RUN apt-get update && apt-get install -y --no-install-recommends cmake git \ unzip build-essential ca-certificates curl zip unzip tar \ @@ -30,7 +30,7 @@ WORKDIR /srv RUN export VCPKG_ROOT=/opt/vcpkg/ && VCPKG_FORCE_SYSTEM_BINARIES=1 cmake --preset linux-release && cmake --build --preset linux-release # Stage 3: load data and execute -FROM ubuntu:23.04 +FROM ubuntu:24.04 VOLUME [ "/data" ] diff --git a/docker/Dockerfile.x86 b/docker/Dockerfile.x86 index 3b035ecfd37..9e75c1078dd 100644 --- a/docker/Dockerfile.x86 +++ b/docker/Dockerfile.x86 @@ -1,5 +1,5 @@ # Stage 1: Download all dependencies -FROM ubuntu:23.04 AS dependencies +FROM ubuntu:24.04 AS dependencies RUN apt-get update && apt-get install -y --no-install-recommends cmake git \ unzip build-essential ca-certificates curl zip unzip tar \ @@ -30,7 +30,7 @@ WORKDIR /srv RUN export VCPKG_ROOT=/opt/vcpkg/ && cmake --preset linux-release && cmake --build --preset linux-release # Stage 3: load data and execute -FROM ubuntu:23.04 +FROM ubuntu:24.04 VOLUME [ "/data" ] COPY --from=build /srv/build/linux-release/bin/canary /bin/canary diff --git a/docs/python-scripts/convert_monsters_callbacks.py b/docs/python-scripts/convert_monsters_callbacks.py new file mode 100644 index 00000000000..140b2562df0 --- /dev/null +++ b/docs/python-scripts/convert_monsters_callbacks.py @@ -0,0 +1,116 @@ +""" +Script for processing Lua files in a project. + +This script is designed to modify `.lua` files in the root directory of the project and all of its subdirectories. +The following modifications are made to each `.lua` file: +1. Remove empty callback functions. +2. Remove the 'onAppear' callback function entirely, including its corresponding `end`. +3. Clean up unnecessary blank lines resulting from the removal of callback functions. + +Usage: +1. Save this script in the `docs/python-scripts` directory of your project. +2. Open a terminal and navigate to the `docs/python-scripts` directory: + cd path/to/your/project/docs/python-scripts +3. Run the script using Python: + python convert_monsters_callbacks.py + +Prerequisites: +- Ensure Python 3 is installed. +- Make sure you have read and write permissions for all `.lua` files in the project directory. + +Output: +- The script will print the root directory being processed. +- At the end, it will output the number of files that were modified. + +Example: +Root path: /path/to/your/project +Script completed. Modified 5 file(s). +""" + +import re +import os + +def get_root_path(): + """Get the root path of the project (two levels above the current script directory).""" + return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) + +def process_lua_code(code): + """Process the Lua code: remove specific callbacks and clean up empty lines. + + Args: + code (str): The Lua code to be processed. + + Returns: + str: The modified Lua code. + """ + # Remove specific callbacks including 'onAppear' and empty callbacks + code = re.sub(r'\n?mType\.onAppear = function\(.*?\)\n(.*?)\nend\n?', '', code, flags=re.DOTALL) + code = re.sub(r'\n?mType\.\w+ = function\(.*?\) end\n?', '', code) + + # Remove extra blank lines created by the removal of callbacks + code = re.sub(r'\n{3,}', '\n\n', code) # Limit multiple blank lines to just two + + return code + +def process_lua_file(file_path): + """Process a single Lua file by applying the required modifications. + + Args: + file_path (str): The path to the Lua file to be processed. + + Returns: + bool: True if the file was modified and saved, False otherwise. + """ + try: + with open(file_path, 'r', encoding='utf-8') as file: + code = file.read() + except Exception as e: + print(f"Error reading file {file_path}: {e}") + return False + + original_code = code + modified_code = process_lua_code(code) + + if modified_code != original_code: + try: + with open(file_path, 'w', encoding='utf-8') as file: + file.write(modified_code) + return True + except Exception as e: + print(f"Error writing file {file_path}: {e}") + return False + +def process_all_lua_files(root_path): + """Process all Lua files in the root path and its subdirectories. + + Args: + root_path (str): The root directory in which to search for Lua files. + + Returns: + int: The count of modified Lua files. + """ + modified_files_count = 0 + + for dirpath, _, filenames in os.walk(root_path): + for filename in filenames: + if filename.endswith(".lua"): + file_path = os.path.join(dirpath, filename) + if process_lua_file(file_path): + modified_files_count += 1 + + return modified_files_count + +def main(): + """Main function to run the script. + + This function determines the root path of the project, processes all Lua files + found in the root path and subdirectories, and prints the number of files modified. + """ + root_path = get_root_path() + print(f"Root path: {root_path}") + + modified_files_count = process_all_lua_files(root_path) + print(f"Script completed. Modified {modified_files_count} file(s).") + +if __name__ == "__main__": + main() diff --git a/docs/python-scripts/modify_lua_script_interfaces.py b/docs/python-scripts/modify_lua_script_interfaces.py new file mode 100644 index 00000000000..881a8453d90 --- /dev/null +++ b/docs/python-scripts/modify_lua_script_interfaces.py @@ -0,0 +1,211 @@ +import os +import re +import argparse + +# Functions that modify the file + +def remove_constructor_and_destructor(content): + # Remove the class constructor and destructor, including a blank line after the destructor + pattern = r"explicit\s+\w+\(lua_State\* L\)\s*:\s*LuaScriptInterface\(\"[^\"]+\"\)\s*\{[^\}]*\}\n\s*~\w+\(\)\s*override\s*=\s*default;\n\s*\n?" + content = re.sub(pattern, "", content, flags=re.DOTALL) + return content + +def remove_include_luascript(content): + # Remove the specified include and the blank line below it + pattern = r'#include\s+"lua/scripts/luascript.hpp"\n\n?' + content = re.sub(pattern, "", content) + return content + +def remove_final_luascriptinterface(content): + # Remove "final : LuaScriptInterface", "public LuaScriptInterface", "final :", and "LuaScriptInterface" alone + pattern = r'final\s*:\s*public\s+LuaScriptInterface|public\s+LuaScriptInterface|final\s*:\s*|LuaScriptInterface\s*' + content = re.sub(pattern, "", content) + # Remove extra spaces between the class name and the opening block + content = re.sub(r'class\s+(\w+)\s*\{', r'class \1 {', content) + return content + +def move_init_function_to_cpp(hpp_content, cpp_content, class_name): + # Extracts the init function from the hpp, keeping the signature + pattern = r'static void init\(lua_State\* L\)\s*\{[^\}]*\}' + match = re.search(pattern, hpp_content, flags=re.DOTALL) + if match: + # Keep the function signature in the hpp, but remove the body + init_function_signature = "static void init(lua_State* L);" + hpp_content = re.sub(pattern, init_function_signature, hpp_content, flags=re.DOTALL) + + # Adjust the function signature for the cpp + init_function = match.group() + init_function = re.sub(r'static void\s+', f'void {class_name}::', init_function) + # Remove extra indentation + init_function = init_function.replace(' \n\t\t', '\n\t') + # Remove the extra tab from the function closure + init_function = init_function.replace('\n\t}', '\n}') + + # Add a blank line before and after the function + init_function = f"\n{init_function}\n" + + # Add the function to the beginning of the cpp, after the includes + last_include = re.findall(r'#include\s+<[^>]+>|#include\s+"[^"]+"', cpp_content) + if last_include: + last_include_pos = cpp_content.rfind(last_include[-1]) + len(last_include[-1]) + cpp_content = cpp_content[:last_include_pos] + "\n" + init_function + cpp_content[last_include_pos:] + else: + cpp_content = init_function + cpp_content + return hpp_content, cpp_content + +def add_include_to_cpp(cpp_content): + # Add the new include after the last include, if it is not already present + include_statement = '#include "lua/functions/lua_functions_loader.hpp"' + if include_statement not in cpp_content: + # Locate the last include + last_include = re.findall(r'#include\s+<[^>]+>|#include\s+"[^"]+"', cpp_content) + if last_include: + last_include_pos = cpp_content.rfind(last_include[-1]) + len(last_include[-1]) + # Make sure there are not multiple line breaks before the include + cpp_content = cpp_content[:last_include_pos].rstrip() + "\n" + include_statement + "\n\n" + cpp_content[last_include_pos:].lstrip() + return cpp_content + +def process_files(hpp_file_path, cpp_file_path): + with open(hpp_file_path, 'r', encoding='utf-8') as hpp_file: + hpp_content = hpp_file.read() + + with open(cpp_file_path, 'r', encoding='utf-8') as cpp_file: + cpp_content = cpp_file.read() + + # Get the class name from the hpp file + class_name_match = re.search(r'class\s+(\w+)', hpp_content) + class_name = class_name_match.group(1) if class_name_match else None + + if class_name: + # Apply all modifications + hpp_content = remove_constructor_and_destructor(hpp_content) + hpp_content = remove_include_luascript(hpp_content) + hpp_content = remove_final_luascriptinterface(hpp_content) + hpp_content, cpp_content = move_init_function_to_cpp(hpp_content, cpp_content, class_name) + cpp_content = add_include_to_cpp(cpp_content) + + # Save the modified files + with open(hpp_file_path, 'w', encoding='utf-8') as hpp_file: + hpp_file.write(hpp_content) + + with open(cpp_file_path, 'w', encoding='utf-8') as cpp_file: + cpp_file.write(cpp_content) + + print(f'Modifications applied to: {hpp_file_path} and {cpp_file_path}') + +def main(directory): + # Scan the specified folder and find all .hpp and .cpp files + for root, _, files in os.walk(directory): + for file in files: + if file.endswith('.hpp'): + hpp_file_path = os.path.join(root, file) + cpp_file_path = hpp_file_path.replace('.hpp', '.cpp') + if os.path.exists(cpp_file_path): + process_files(hpp_file_path, cpp_file_path) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Apply modifications to .hpp and .cpp files according to specifications.') + parser.add_argument('directory', type=str, nargs='?', default='../../src/lua/functions/', help='Path of the directory to be scanned.') + args = parser.parse_args() + + main(args.directory) + +# Functions you want to migrate to static calls +functions_to_convert = [ + "getNumber", + "getBoolean", + "getString", + "getUserdata", + "getScriptEnv", + "getCreature", + "getPlayer", + "getPosition", + "getOutfit", + "getThing", + "getUserdataShared", + "getUserdataType", + "getRawUserDataShared", + "getErrorDesc", + "getFormatedLoggerMessage", + "getField", + "getFieldString", + "getVariant", + "getGuild", + "isTable", + "isString", + "isNumber", + "isBoolean", + "isNil", + "isFunction", + "isUserdata", + "reportError", + "reportErrorFunc", + "pushInstantSpell", + "pushVariant", + "pushOutfit", + "pushCylinder", + "pushBoolean", + "pushString", + "pushUserdata", + "pushPosition", + "setMetatable", + "setWeakMetatable", + "setCreatureMetatable", + "setItemMetatable", + "setField", + "registerVariable", + "registerGlobalMethod", + "registerGlobalVariable", + "registerGlobalBoolean", + "registerMethod", + "registerClass", + "registerTable", + "registerSharedClass", + "registerMetaMethod", +] + +# Files you want to exclude from scanning (relative paths) +files_to_exclude = [ + os.path.normpath("lua_functions_loader.cpp"), + os.path.normpath("lua_functions_loader.hpp") +] + +def convert_to_static(file_path): + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + original_content = content # Keep the original content to check for changes + + for function in functions_to_convert: + # Regex to capture function calls and replace them with Lua::function + # Skip calls that are part of g_configManager() and handle both regular and template functions + pattern = r'(?)?\(' + replacement = rf'Lua::{function}\1(' + content = re.sub(pattern, replacement, content) + + if content != original_content: + with open(file_path, 'w', encoding='utf-8') as file: + file.write(content) + print(f'File converted: {file_path}') + else: + print(f'No changes made to file: {file_path}') + +def main(directory): + # Scan the specified folder and find all .cpp and .hpp files + for root, _, files in os.walk(directory): + for file in files: + if file.endswith(('.cpp', '.hpp')): + file_path = os.path.normpath(os.path.join(root, file)) + + # Check if the file is in the exclusion list + if any(os.path.basename(file_path) == exclude_file for exclude_file in files_to_exclude): + print(f'File ignored: {file_path}') + continue # Skip the specified files + + convert_to_static(file_path) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Convert functions to static calls.') + parser.add_argument('directory', type=str, nargs='?', default='../../src/lua/functions/', help='Path of the directory to be scanned.') + + main(args.directory) diff --git a/docs/python-scripts/normalize_cpp_own_includes.py.py b/docs/python-scripts/normalize_cpp_own_includes.py.py new file mode 100644 index 00000000000..d5e0ca0e858 --- /dev/null +++ b/docs/python-scripts/normalize_cpp_own_includes.py.py @@ -0,0 +1,72 @@ +import os + +# Path to the directory containing C++ files (.cpp) +directory_path = "path/to/src" + +def normalize_include_line(line): + # Normalize the include line by removing extra spaces and using '/' as separator + return ' '.join(line.strip().split()).replace('\\', '/') + +def correct_include_path(line, correct_include): + # Check if the include line matches the correct include, regardless of the path + if line.strip().startswith('#include') and ('"' + correct_include.split('/')[-1] + '"') in line: + return f'#include "{correct_include}"\n' + return line + +# Function to modify files and correct their own includes +def modify_includes(directory): + for root, dirs, files in os.walk(directory): + for filename in files: + if filename.endswith('.cpp'): + file_path = os.path.join(root, filename) + correct_include = f"{os.path.relpath(root, directory).replace('\\', '/')}/{filename.replace('.cpp', '.hpp')}" + + # Remove './' from the beginning of the path, if present + if correct_include.startswith('./'): + correct_include = correct_include[2:] + + include_statement = f'#include "{correct_include}"\n' + + with open(file_path, 'r', encoding='utf8') as file: + lines = file.readlines() + + corrected_lines = [] + include_found = False + include_renamed = False + include_at_correct_position = False + + # Normalize lines and correct includes as necessary + for i, line in enumerate(lines): + normalized_line = normalize_include_line(line) + if correct_include in normalized_line: + # If the correct include was found and is in the correct position + include_found = True + if i == next((idx for idx, l in enumerate(lines) if l.strip().startswith('#include')), i): + include_at_correct_position = True + if include_at_correct_position: + corrected_lines.append(line) # Keep the original include if it is correct and in the right position + elif filename.replace('.cpp', '.hpp') in normalized_line: + # Replace any old version of the include with the corrected version + corrected_lines.append(correct_include_path(line, correct_include)) + include_renamed = True + else: + corrected_lines.append(line) + + # If the include was found but not in the correct position, or was renamed, move it to the first include position + if (include_found and not include_at_correct_position) or include_renamed: + # Remove any occurrence of the correct include that is out of place + corrected_lines = [line for line in corrected_lines if line.strip() != include_statement.strip()] + # Find the first include position and insert the correct include + first_include_index = next((i for i, line in enumerate(corrected_lines) if line.strip().startswith('#include')), len(corrected_lines)) + corrected_lines.insert(first_include_index, include_statement) + # Add a blank line immediately after the first include, if necessary + if first_include_index + 1 < len(corrected_lines) and not corrected_lines[first_include_index + 1].isspace(): + corrected_lines.insert(first_include_index + 1, '\n') + + # Write the changes back to the file only if modifications were made + if corrected_lines != lines: + with open(file_path, 'w', encoding='utf8') as file: + file.writelines(corrected_lines) + +# Call the function to modify the files +modify_includes(directory_path) diff --git a/schema.sql b/schema.sql index af245067057..86ea9e1bf6b 100644 --- a/schema.sql +++ b/schema.sql @@ -70,7 +70,7 @@ CREATE TABLE IF NOT EXISTS `players` ( `posx` int(11) NOT NULL DEFAULT '0', `posy` int(11) NOT NULL DEFAULT '0', `posz` int(11) NOT NULL DEFAULT '0', - `conditions` blob NOT NULL, + `conditions` mediumblob NOT NULL, `cap` int(11) NOT NULL DEFAULT '0', `sex` int(11) NOT NULL DEFAULT '0', `pronoun` int(11) NOT NULL DEFAULT '0', diff --git a/src/account/account.cpp b/src/account/account.cpp index 2cd411ef3e7..93596f77b15 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -10,138 +10,141 @@ #include "account/account.hpp" #include "account/account_repository_db.hpp" -#include "config/configmanager.hpp" -#include "utils/definitions.hpp" +#include "account/account_info.hpp" #include "security/argon.hpp" #include "utils/tools.hpp" - -#include "enums/account_type.hpp" #include "enums/account_coins.hpp" #include "enums/account_errors.hpp" +#include "enums/account_type.hpp" Account::Account(const uint32_t &id) { m_descriptor.clear(); - m_account.id = id; - m_account.premiumRemainingDays = 0; - m_account.premiumLastDay = 0; - m_account.accountType = ACCOUNT_TYPE_NORMAL; + m_account = std::make_unique(); + m_account->id = id; + m_account->premiumRemainingDays = 0; + m_account->premiumLastDay = 0; + m_account->accountType = ACCOUNT_TYPE_NORMAL; } Account::Account(std::string descriptor) : m_descriptor(std::move(descriptor)) { - m_account.id = 0; - m_account.premiumRemainingDays = 0; - m_account.premiumLastDay = 0; - m_account.accountType = ACCOUNT_TYPE_NORMAL; + m_account = std::make_unique(); + m_account->id = 0; + m_account->premiumRemainingDays = 0; + m_account->premiumLastDay = 0; + m_account->accountType = ACCOUNT_TYPE_NORMAL; } -uint8_t Account::load() { - if (m_account.id != 0 && g_accountRepository().loadByID(m_account.id, m_account)) { +AccountErrors_t Account::load() { + using enum AccountErrors_t; + if (m_account->id != 0 && g_accountRepository().loadByID(m_account->id, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } if (!m_descriptor.empty() && g_accountRepository().loadByEmailOrName(getProtocolCompat(), m_descriptor, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } if (!m_descriptor.empty() && g_accountRepository().loadBySession(m_descriptor, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } updatePremiumTime(); - return enumToValue(AccountErrors_t::LoadingAccount); + return LoadingAccount; } -uint8_t Account::reload() { +AccountErrors_t Account::reload() { if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return AccountErrors_t::NotInitialized; } return load(); } -uint8_t Account::save() { +AccountErrors_t Account::save() const { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } - if (!g_accountRepository().save(m_account)) { - return enumToValue(AccountErrors_t::Storage); + return Storage; } - - return enumToValue(AccountErrors_t::Ok); + return Ok; } -std::tuple Account::getCoins(const uint8_t &type) const { +std::tuple Account::getCoins(CoinType type) const { + using enum AccountErrors_t; if (!m_accLoaded) { - return { 0, enumToValue(AccountErrors_t::NotInitialized) }; + return { 0, NotInitialized }; } uint32_t coins = 0; - if (!g_accountRepository().getCoins(m_account.id, type, coins)) { - return { 0, enumToValue(AccountErrors_t::Storage) }; + if (!g_accountRepository().getCoins(m_account->id, type, coins)) { + return { 0, Storage }; } - return { coins, enumToValue(AccountErrors_t::Ok) }; + return { coins, Ok }; } -uint8_t Account::addCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail) { +AccountErrors_t Account::addCoins(CoinType type, const uint32_t &amount, const std::string &detail) { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } if (amount == 0) { - return enumToValue(AccountErrors_t::Ok); + return Ok; } auto [coins, result] = getCoins(type); - if (AccountErrors_t::Ok != enumFromValue(result)) { + if (Ok != result) { return result; } - if (!g_accountRepository().setCoins(m_account.id, type, coins + amount)) { - return enumToValue(AccountErrors_t::Storage); + if (!g_accountRepository().setCoins(m_account->id, type, coins + amount)) { + return Storage; } - registerCoinTransaction(enumToValue(CoinTransactionType::Add), type, amount, detail); + registerCoinTransaction(CoinTransactionType::Add, type, amount, detail); - return enumToValue(AccountErrors_t::Ok); + return Ok; } -uint8_t Account::removeCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail) { +AccountErrors_t Account::removeCoins(CoinType type, const uint32_t &amount, const std::string &detail) { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } if (amount == 0) { - return enumToValue(AccountErrors_t::Ok); + return Ok; } auto [coins, result] = getCoins(type); - if (AccountErrors_t::Ok != enumFromValue(result)) { + if (Ok != result) { return result; } if (coins < amount) { g_logger().info("Account doesn't have enough coins! current[{}], remove:[{}]", coins, amount); - return enumToValue(AccountErrors_t::RemoveCoins); + return RemoveCoins; } - if (!g_accountRepository().setCoins(m_account.id, type, coins - amount)) { - return enumToValue(AccountErrors_t::Storage); + if (!g_accountRepository().setCoins(m_account->id, type, coins - amount)) { + return Storage; } - registerCoinTransaction(enumToValue(CoinTransactionType::Remove), type, amount, detail); + registerCoinTransaction(CoinTransactionType::Remove, type, amount, detail); - return enumToValue(AccountErrors_t::Ok); + return Ok; } -void Account::registerCoinTransaction(const uint8_t &transactionType, const uint8_t &type, const uint32_t &amount, const std::string &detail) { +void Account::registerCoinTransaction(CoinTransactionType transactionType, CoinType type, const uint32_t &amount, const std::string &detail) { if (!m_accLoaded) { return; } @@ -150,17 +153,17 @@ void Account::registerCoinTransaction(const uint8_t &transactionType, const uint return; } - if (!g_accountRepository().registerCoinsTransaction(m_account.id, transactionType, amount, type, detail)) { + if (!g_accountRepository().registerCoinsTransaction(m_account->id, transactionType, amount, type, detail)) { g_logger().error( "Failed to register transaction: 'account:[{}], transaction " "type:[{}], coins:[{}], coin type:[{}], description:[{}]", - m_account.id, transactionType, amount, type, detail + m_account->id, transactionType, amount, type, detail ); } } [[nodiscard]] uint32_t Account::getID() const { - return m_account.id; + return m_account->id; }; std::string Account::getDescriptor() const { @@ -173,61 +176,61 @@ std::string Account::getPassword() { } std::string password; - if (!g_accountRepository().getPassword(m_account.id, password)) { + if (!g_accountRepository().getPassword(m_account->id, password)) { password.clear(); - g_logger().error("Failed to get password for account[{}]!", m_account.id); + g_logger().error("Failed to get password for account[{}]!", m_account->id); } return password; } void Account::addPremiumDays(const int32_t &days) { - auto timeLeft = std::max(0, static_cast((m_account.premiumLastDay - getTimeNow()) % 86400)); - setPremiumDays(m_account.premiumRemainingDays + days); - m_account.premiumDaysPurchased += days; + auto timeLeft = std::max(0, static_cast((m_account->premiumLastDay - getTimeNow()) % 86400)); + setPremiumDays(m_account->premiumRemainingDays + days); + m_account->premiumDaysPurchased += days; if (timeLeft > 0) { - m_account.premiumLastDay += timeLeft; + m_account->premiumLastDay += timeLeft; } } void Account::setPremiumDays(const int32_t &days) { - m_account.premiumRemainingDays = days; - m_account.premiumLastDay = getTimeNow() + (days * 86400); + m_account->premiumRemainingDays = days; + m_account->premiumLastDay = getTimeNow() + (days * 86400); if (days <= 0) { - m_account.premiumLastDay = 0; - m_account.premiumRemainingDays = 0; + m_account->premiumLastDay = 0; + m_account->premiumRemainingDays = 0; } } [[nodiscard]] uint32_t Account::getPremiumRemainingDays() const { - return m_account.premiumLastDay > getTimeNow() ? static_cast((m_account.premiumLastDay - getTimeNow()) / 86400) : 0; + return m_account->premiumLastDay > getTimeNow() ? static_cast((m_account->premiumLastDay - getTimeNow()) / 86400) : 0; } [[nodiscard]] uint32_t Account::getPremiumDaysPurchased() const { - return m_account.premiumDaysPurchased; + return m_account->premiumDaysPurchased; } -uint8_t Account::setAccountType(const uint8_t &accountType) { - m_account.accountType = accountType; - return enumToValue(AccountErrors_t::Ok); +AccountErrors_t Account::setAccountType(AccountType accountType) { + m_account->accountType = accountType; + return AccountErrors_t::Ok; } -[[nodiscard]] uint8_t Account::getAccountType() const { - return m_account.accountType; +[[nodiscard]] AccountType Account::getAccountType() const { + return m_account->accountType; } void Account::updatePremiumTime() { - time_t lastDay = m_account.premiumLastDay; - uint32_t remainingDays = m_account.premiumRemainingDays; + time_t lastDay = m_account->premiumLastDay; + uint32_t remainingDays = m_account->premiumRemainingDays; time_t currentTime = getTimeNow(); auto daysLeft = static_cast((lastDay - currentTime) / 86400); auto timeLeft = static_cast((lastDay - currentTime) % 86400); - m_account.premiumRemainingDays = daysLeft > 0 ? daysLeft : 0; + m_account->premiumRemainingDays = daysLeft > 0 ? daysLeft : 0; if (daysLeft == 0 && timeLeft == 0) { setPremiumDays(0); @@ -237,26 +240,27 @@ void Account::updatePremiumTime() { setPremiumDays(0); } - if (remainingDays == m_account.premiumRemainingDays) { + if (remainingDays == m_account->premiumRemainingDays) { return; } - if (AccountErrors_t::Ok != enumFromValue(save())) { + if (AccountErrors_t::Ok != save()) { g_logger().error("Failed to update account premium time: [{}]", getDescriptor()); } } -std::tuple, uint8_t> +std::tuple, AccountErrors_t> Account::getAccountPlayers() const { - auto valueToReturn = enumToValue(m_accLoaded ? AccountErrors_t::Ok : AccountErrors_t::NotInitialized); - return { m_account.players, valueToReturn }; + using enum AccountErrors_t; + auto valueToReturn = m_accLoaded ? Ok : NotInitialized; + return { m_account->players, valueToReturn }; } void Account::setProtocolCompat(bool toggle) { - m_account.oldProtocol = toggle; + m_account->oldProtocol = toggle; } bool Account::getProtocolCompat() const { - return m_account.oldProtocol; + return m_account->oldProtocol; } bool Account::authenticate() { @@ -269,8 +273,8 @@ bool Account::authenticate(const std::string &secret) { } bool Account::authenticateSession() { - if (m_account.sessionExpires < getTimeNow()) { - g_logger().error("Session expired for account[{}] expired at [{}] current time [{}]!", m_account.id, m_account.sessionExpires, getTimeNow()); + if (m_account->sessionExpires < getTimeNow()) { + g_logger().error("Session expired for account[{}] expired at [{}] current time [{}]!", m_account->id, m_account->sessionExpires, getTimeNow()); return false; } return true; @@ -290,9 +294,9 @@ bool Account::authenticatePassword(const std::string &password) { } uint32_t Account::getAccountAgeInDays() const { - return static_cast(std::ceil((getTimeNow() - m_account.creationTime) / 86400)); + return static_cast(std::ceil((getTimeNow() - m_account->creationTime) / 86400)); } [[nodiscard]] time_t Account::getPremiumLastDay() const { - return m_account.premiumLastDay; + return m_account->premiumLastDay; } diff --git a/src/account/account.hpp b/src/account/account.hpp index d968ba8ddfb..2c6098a8dbd 100644 --- a/src/account/account.hpp +++ b/src/account/account.hpp @@ -9,13 +9,20 @@ #pragma once -#include "account/account_info.hpp" +struct AccountInfo; + +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; +enum class AccountErrors_t : uint8_t; +enum AccountType : uint8_t; class Account { public: explicit Account(const uint32_t &id); explicit Account(std::string descriptor); + ~Account() = default; + /** Coins * @brief Get the amount of coins that the account has from database. * @@ -24,7 +31,7 @@ class Account { * @return uint32_t Number of coins * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - [[nodiscard]] std::tuple getCoins(const uint8_t &type) const; + [[nodiscard]] std::tuple getCoins(CoinType type) const; /** * @brief Add coins to the account. @@ -33,7 +40,7 @@ class Account { * @param amount Amount of coins to be added * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t addCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail = "ADD Coins"); + AccountErrors_t addCoins(CoinType type, const uint32_t &amount, const std::string &detail = "ADD Coins"); /** * @brief Removes coins from the account. @@ -42,7 +49,7 @@ class Account { * @param amount Amount of coins to be removed * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t removeCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail = "REMOVE Coins"); + AccountErrors_t removeCoins(CoinType type, const uint32_t &amount, const std::string &detail = "REMOVE Coins"); /** * @brief Registers a coin transaction. @@ -51,7 +58,7 @@ class Account { * @param amount Amount of coins to be added * @param detail Detail of the transaction */ - void registerCoinTransaction(const uint8_t &transactionType, const uint8_t &type, const uint32_t &amount, const std::string &detail); + void registerCoinTransaction(CoinTransactionType transactionType, CoinType type, const uint32_t &amount, const std::string &detail); /*************************************************************************** * Account Load/Save @@ -62,14 +69,14 @@ class Account { * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t save(); + AccountErrors_t save() const; /** * @brief Load Account Information. * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t load(); + AccountErrors_t load(); /** * @brief Re-Load Account Information to get update information(mainly the @@ -77,7 +84,7 @@ class Account { * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t reload(); + AccountErrors_t reload(); /*************************************************************************** * Setters and Getters @@ -105,12 +112,12 @@ class Account { [[nodiscard]] time_t getPremiumLastDay() const; - uint8_t setAccountType(const uint8_t &accountType); - [[nodiscard]] uint8_t getAccountType() const; + AccountErrors_t setAccountType(AccountType accountType); + [[nodiscard]] AccountType getAccountType() const; void updatePremiumTime(); - std::tuple, uint8_t> getAccountPlayers() const; + std::tuple, AccountErrors_t> getAccountPlayers() const; // Old protocol compat void setProtocolCompat(bool toggle); @@ -126,6 +133,6 @@ class Account { private: std::string m_descriptor; - AccountInfo m_account; + std::unique_ptr m_account; bool m_accLoaded = false; }; diff --git a/src/account/account_info.hpp b/src/account/account_info.hpp index 698c3b96c1c..b9dad60dbbc 100644 --- a/src/account/account_info.hpp +++ b/src/account/account_info.hpp @@ -14,11 +14,15 @@ #include #endif +#include "enums/account_type.hpp" + struct AccountInfo { + ~AccountInfo() = default; + uint32_t id = 0; uint32_t premiumRemainingDays = 0; time_t premiumLastDay = 0; - uint8_t accountType = 0; + AccountType accountType = ACCOUNT_TYPE_NONE; phmap::flat_hash_map players; bool oldProtocol = false; time_t sessionExpires = 0; diff --git a/src/account/account_repository.hpp b/src/account/account_repository.hpp index 6dfe2c65668..5a9cd5292c3 100644 --- a/src/account/account_repository.hpp +++ b/src/account/account_repository.hpp @@ -11,6 +11,9 @@ struct AccountInfo; +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; + class AccountRepository { public: AccountRepository() = default; @@ -22,22 +25,22 @@ class AccountRepository { static AccountRepository &getInstance(); - virtual bool loadByID(const uint32_t &id, AccountInfo &acc) = 0; - virtual bool loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, AccountInfo &acc) = 0; - virtual bool loadBySession(const std::string &email, AccountInfo &acc) = 0; - virtual bool save(const AccountInfo &accInfo) = 0; + virtual bool loadByID(const uint32_t &id, std::unique_ptr &acc) = 0; + virtual bool loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, std::unique_ptr &acc) = 0; + virtual bool loadBySession(const std::string &email, std::unique_ptr &acc) = 0; + virtual bool save(const std::unique_ptr &accInfo) = 0; virtual bool getCharacterByAccountIdAndName(const uint32_t &id, const std::string &name) = 0; virtual bool getPassword(const uint32_t &id, std::string &password) = 0; - virtual bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) = 0; - virtual bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) = 0; + virtual bool getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) = 0; + virtual bool setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) = 0; virtual bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) = 0; }; diff --git a/src/account/account_repository_db.cpp b/src/account/account_repository_db.cpp index 10f3d6f3a41..c3f02bfe972 100644 --- a/src/account/account_repository_db.cpp +++ b/src/account/account_repository_db.cpp @@ -10,27 +10,30 @@ #include "account/account_repository_db.hpp" #include "database/database.hpp" +#include "enums/account_coins.hpp" #include "utils/definitions.hpp" #include "utils/tools.hpp" -#include "enums/account_type.hpp" -#include "enums/account_coins.hpp" -#include "account/account_info.hpp" -AccountRepositoryDB::AccountRepositoryDB() : - coinTypeToColumn({ { enumToValue(CoinType::Normal), "coins" }, { enumToValue(CoinType::Tournament), "tournament_coins" }, { enumToValue(CoinType::Transferable), "coins_transferable" } }) { } +AccountRepositoryDB::AccountRepositoryDB() { + coinTypeToColumn = { + { CoinType::Normal, "coins" }, + { CoinType::Tournament, "coins_tournament" }, + { CoinType::Transferable, "coins_transferable" } + }; +} -bool AccountRepositoryDB::loadByID(const uint32_t &id, AccountInfo &acc) { +bool AccountRepositoryDB::loadByID(const uint32_t &id, std::unique_ptr &acc) { auto query = fmt::format("SELECT `id`, `type`, `premdays`, `lastday`, `creation`, `premdays_purchased`, 0 AS `expires` FROM `accounts` WHERE `id` = {}", id); return load(query, acc); }; -bool AccountRepositoryDB::loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, AccountInfo &acc) { +bool AccountRepositoryDB::loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, std::unique_ptr &acc) { auto identifier = oldProtocol ? "name" : "email"; auto query = fmt::format("SELECT `id`, `type`, `premdays`, `lastday`, `creation`, `premdays_purchased`, 0 AS `expires` FROM `accounts` WHERE `{}` = {}", identifier, g_database().escapeString(emailOrName)); return load(query, acc); }; -bool AccountRepositoryDB::loadBySession(const std::string &sessionKey, AccountInfo &acc) { +bool AccountRepositoryDB::loadBySession(const std::string &sessionKey, std::unique_ptr &acc) { auto query = fmt::format( "SELECT `accounts`.`id`, `type`, `premdays`, `lastday`, `creation`, `premdays_purchased`, `account_sessions`.`expires` " "FROM `accounts` " @@ -41,21 +44,21 @@ bool AccountRepositoryDB::loadBySession(const std::string &sessionKey, AccountIn return load(query, acc); }; -bool AccountRepositoryDB::save(const AccountInfo &accInfo) { +bool AccountRepositoryDB::save(const std::unique_ptr &accInfo) { bool successful = g_database().executeQuery( fmt::format( "UPDATE `accounts` SET `type` = {}, `premdays` = {}, `lastday` = {}, `creation` = {}, `premdays_purchased` = {} WHERE `id` = {}", - accInfo.accountType, - accInfo.premiumRemainingDays, - accInfo.premiumLastDay, - accInfo.creationTime, - accInfo.premiumDaysPurchased, - accInfo.id + accInfo->accountType, + accInfo->premiumRemainingDays, + accInfo->premiumLastDay, + accInfo->creationTime, + accInfo->premiumDaysPurchased, + accInfo->id ) ); if (!successful) { - g_logger().error("Failed to save account:[{}]", accInfo.id); + g_logger().error("Failed to save account:[{}]", accInfo->id); } return successful; @@ -82,15 +85,18 @@ bool AccountRepositoryDB::getPassword(const uint32_t &id, std::string &password) return true; }; -bool AccountRepositoryDB::getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) { - if (coinTypeToColumn.find(type) == coinTypeToColumn.end()) { - g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, type); +bool AccountRepositoryDB::getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) { + auto it = coinTypeToColumn.find(coinType); + if (it == coinTypeToColumn.end()) { + g_logger().error("[{}] invalid coin type:[{}]", __FUNCTION__, coinType); return false; } - auto result = g_database().storeQuery(fmt::format( + auto column = it->second; + + const auto result = g_database().storeQuery(fmt::format( "SELECT `{}` FROM `accounts` WHERE `id` = {}", - coinTypeToColumn.at(type), + column, id )); @@ -98,20 +104,23 @@ bool AccountRepositoryDB::getCoins(const uint32_t &id, const uint8_t &type, uint return false; } - coins = result->getNumber(coinTypeToColumn.at(type)); + coins = result->getNumber(column); return true; }; -bool AccountRepositoryDB::setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) { - if (coinTypeToColumn.find(type) == coinTypeToColumn.end()) { - g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, type); +bool AccountRepositoryDB::setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) { + auto it = coinTypeToColumn.find(coinType); + if (it == coinTypeToColumn.end()) { + g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, coinType); return false; } - bool successful = g_database().executeQuery(fmt::format( + auto column = it->second; + + const bool successful = g_database().executeQuery(fmt::format( "UPDATE `accounts` SET `{}` = {} WHERE `id` = {}", - coinTypeToColumn.at(type), + column, amount, id )); @@ -125,9 +134,9 @@ bool AccountRepositoryDB::setCoins(const uint32_t &id, const uint8_t &type, cons bool AccountRepositoryDB::registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) { bool successful = g_database().executeQuery( @@ -155,13 +164,13 @@ bool AccountRepositoryDB::registerCoinsTransaction( return successful; }; -bool AccountRepositoryDB::loadAccountPlayers(AccountInfo &acc) { +bool AccountRepositoryDB::loadAccountPlayers(std::unique_ptr &acc) const { auto result = g_database().storeQuery( - fmt::format("SELECT `name`, `deletion` FROM `players` WHERE `account_id` = {} ORDER BY `name` ASC", acc.id) + fmt::format("SELECT `name`, `deletion` FROM `players` WHERE `account_id` = {} ORDER BY `name` ASC", acc->id) ); if (!result) { - g_logger().error("Failed to load account[{}] players!", acc.id); + g_logger().error("Failed to load account[{}] players!", acc->id); return false; } @@ -170,43 +179,43 @@ bool AccountRepositoryDB::loadAccountPlayers(AccountInfo &acc) { continue; } - acc.players.try_emplace({ result->getString("name"), result->getNumber("deletion") }); + acc->players.try_emplace({ result->getString("name"), result->getNumber("deletion") }); } while (result->next()); return true; } -bool AccountRepositoryDB::load(const std::string &query, AccountInfo &acc) { +bool AccountRepositoryDB::load(const std::string &query, std::unique_ptr &acc) { auto result = g_database().storeQuery(query); if (result == nullptr) { return false; } - acc.id = result->getNumber("id"); - acc.accountType = result->getNumber("type"); - acc.premiumLastDay = result->getNumber("lastday"); - acc.sessionExpires = result->getNumber("expires"); - acc.premiumDaysPurchased = result->getNumber("premdays_purchased"); - acc.creationTime = result->getNumber("creation"); - acc.premiumRemainingDays = acc.premiumLastDay > getTimeNow() ? (acc.premiumLastDay - getTimeNow()) / 86400 : 0; + acc->id = result->getNumber("id"); + acc->accountType = result->getNumber("type"); + acc->premiumLastDay = result->getNumber("lastday"); + acc->sessionExpires = result->getNumber("expires"); + acc->premiumDaysPurchased = result->getNumber("premdays_purchased"); + acc->creationTime = result->getNumber("creation"); + acc->premiumRemainingDays = acc->premiumLastDay > getTimeNow() ? (acc->premiumLastDay - getTimeNow()) / 86400 : 0; setupLoyaltyInfo(acc); return loadAccountPlayers(acc); } -void AccountRepositoryDB::setupLoyaltyInfo(AccountInfo &acc) { - if (acc.premiumDaysPurchased >= acc.premiumRemainingDays && acc.creationTime != 0) { +void AccountRepositoryDB::setupLoyaltyInfo(std::unique_ptr &acc) { + if (acc->premiumDaysPurchased >= acc->premiumRemainingDays && acc->creationTime != 0) { return; } - if (acc.premiumDaysPurchased < acc.premiumRemainingDays) { - acc.premiumDaysPurchased = acc.premiumRemainingDays; + if (acc->premiumDaysPurchased < acc->premiumRemainingDays) { + acc->premiumDaysPurchased = acc->premiumRemainingDays; } - if (acc.creationTime == 0) { - acc.creationTime = getTimeNow(); + if (acc->creationTime == 0) { + acc->creationTime = getTimeNow(); } save(acc); diff --git a/src/account/account_repository_db.hpp b/src/account/account_repository_db.hpp index e34d864a090..e7a11c15e51 100644 --- a/src/account/account_repository_db.hpp +++ b/src/account/account_repository_db.hpp @@ -11,32 +11,36 @@ #include "account/account_repository.hpp" +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; + class AccountRepositoryDB final : public AccountRepository { public: AccountRepositoryDB(); - bool loadByID(const uint32_t &id, AccountInfo &acc) override; - bool loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, AccountInfo &acc) override; - bool loadBySession(const std::string &esseionKey, AccountInfo &acc) override; - bool save(const AccountInfo &accInfo) override; + bool loadByID(const uint32_t &id, std::unique_ptr &acc) override; + bool loadByEmailOrName(bool oldProtocol, const std::string &emailOrName, std::unique_ptr &acc) override; + bool loadBySession(const std::string &esseionKey, std::unique_ptr &acc) override; + bool save(const std::unique_ptr &accInfo) override; bool getCharacterByAccountIdAndName(const uint32_t &id, const std::string &name) override; bool getPassword(const uint32_t &id, std::string &password) override; - bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) override; - bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) override; + bool getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) override; + bool setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) override; bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) override; private: - const std::map coinTypeToColumn; - bool load(const std::string &query, AccountInfo &acc); - bool loadAccountPlayers(AccountInfo &acc); - void setupLoyaltyInfo(AccountInfo &acc); + std::unordered_map coinTypeToColumn {}; + + bool load(const std::string &query, std::unique_ptr &acc); + bool loadAccountPlayers(std::unique_ptr &acc) const; + void setupLoyaltyInfo(std::unique_ptr &acc); }; diff --git a/src/canary_server.cpp b/src/canary_server.cpp index aaf1de80530..8dfbcfc954c 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -9,15 +9,21 @@ #include "canary_server.hpp" -#include "declarations.hpp" +#include "core.hpp" +#include "config/configmanager.hpp" +#include "creatures/npcs/npcs.hpp" #include "creatures/players/grouping/familiars.hpp" +#include "creatures/players/imbuements/imbuements.hpp" #include "creatures/players/storages/storages.hpp" #include "database/databasemanager.hpp" +#include "declarations.hpp" #include "game/game.hpp" -#include "game/zones/zone.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/events_scheduler.hpp" +#include "game/zones/zone.hpp" +#include "io/io_bosstiary.hpp" #include "io/iomarket.hpp" +#include "io/ioprey.hpp" #include "lib/thread/thread_pool.hpp" #include "lua/creature/events.hpp" #include "lua/modules/modules.hpp" @@ -26,10 +32,7 @@ #include "server/network/protocol/protocollogin.hpp" #include "server/network/protocol/protocolstatus.hpp" #include "server/network/webhook/webhook.hpp" -#include "io/ioprey.hpp" -#include "io/io_bosstiary.hpp" - -#include "core.hpp" +#include "creatures/players/vocations/vocation.hpp" CanaryServer::CanaryServer( Logger &logger, @@ -319,6 +322,7 @@ void CanaryServer::initializeDatabase() { && !DatabaseManager::optimizeTables()) { logger.debug("No tables were optimized"); } + g_logger().info("Database connection established!"); } void CanaryServer::loadModules() { diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index aa028b52284..1c00df76c2f 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -8,9 +8,11 @@ */ #include "config/configmanager.hpp" + #include "lib/di/container.hpp" #include "game/game.hpp" #include "server/network/webhook/webhook.hpp" +#include "utils/tools.hpp" #if LUA_VERSION_NUM >= 502 #undef lua_strlen diff --git a/src/creatures/appearance/mounts/mounts.cpp b/src/creatures/appearance/mounts/mounts.cpp index e68610fc51e..4b40d383543 100644 --- a/src/creatures/appearance/mounts/mounts.cpp +++ b/src/creatures/appearance/mounts/mounts.cpp @@ -8,6 +8,8 @@ */ #include "creatures/appearance/mounts/mounts.hpp" + +#include "config/configmanager.hpp" #include "game/game.hpp" #include "utils/pugicast.hpp" #include "utils/tools.hpp" diff --git a/src/creatures/appearance/outfit/outfit.cpp b/src/creatures/appearance/outfit/outfit.cpp index 7826ff71e37..4910f937bc3 100644 --- a/src/creatures/appearance/outfit/outfit.cpp +++ b/src/creatures/appearance/outfit/outfit.cpp @@ -8,9 +8,15 @@ */ #include "creatures/appearance/outfit/outfit.hpp" + +#include "config/configmanager.hpp" +#include "creatures/players/player.hpp" +#include "game/game.hpp" +#include "lib/di/container.hpp" #include "utils/pugicast.hpp" #include "utils/tools.hpp" -#include "game/game.hpp" + +std::vector> outfits[PLAYERSEX_LAST + 1]; Outfits &Outfits::getInstance() { return inject(); @@ -101,3 +107,17 @@ std::shared_ptr Outfits::getOutfitByLookType(const std::shared_ptr> &Outfits::getOutfits(PlayerSex_t sex) const { + return outfits[sex]; +} + +std::shared_ptr Outfits::getOutfitByName(PlayerSex_t sex, const std::string &name) const { + for (const auto &outfit : outfits[sex]) { + if (outfit->name == name) { + return outfit; + } + } + + return nullptr; +} diff --git a/src/creatures/appearance/outfit/outfit.hpp b/src/creatures/appearance/outfit/outfit.hpp index c4d49a7f1a2..2d9488449aa 100644 --- a/src/creatures/appearance/outfit/outfit.hpp +++ b/src/creatures/appearance/outfit/outfit.hpp @@ -9,9 +9,7 @@ #pragma once -#include "declarations.hpp" -#include "lib/di/container.hpp" - +enum PlayerSex_t : uint8_t; class Player; struct OutfitEntry { @@ -50,20 +48,7 @@ class Outfits { bool loadFromXml(); [[nodiscard]] std::shared_ptr getOutfitByLookType(const std::shared_ptr &player, uint16_t lookType, bool isOppositeOutfit = false) const; - [[nodiscard]] const std::vector> &getOutfits(PlayerSex_t sex) const { - return outfits[sex]; - } - - std::shared_ptr getOutfitByName(PlayerSex_t sex, const std::string &name) const { - for (const auto &outfit : outfits[sex]) { - if (outfit->name == name) { - return outfit; - } - } - - return nullptr; - } + [[nodiscard]] const std::vector> &getOutfits(PlayerSex_t sex) const; -private: - std::vector> outfits[PLAYERSEX_LAST + 1]; + std::shared_ptr getOutfitByName(PlayerSex_t sex, const std::string &name) const; }; diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index 9aefb280bbf..6b7667a71a5 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -7,24 +7,31 @@ * Website: https://docs.opentibiabr.com/ */ -#include "declarations.hpp" #include "creatures/combat/combat.hpp" -#include "lua/creature/events.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/combat/spells.hpp" +#include "creatures/monsters/monster.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/players/grouping/party.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/imbuements/imbuements.hpp" #include "creatures/players/wheel/player_wheel.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "io/iobestiary.hpp" -#include "creatures/monsters/monster.hpp" -#include "creatures/monsters/monsters.hpp" +#include "io/ioprey.hpp" +#include "creatures/players/vocations/vocation.hpp" #include "items/weapons/weapons.hpp" -#include "map/spectators.hpp" #include "lib/metrics/metrics.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/events.hpp" +#include "map/spectators.hpp" +#include "creatures/players/player.hpp" -int32_t Combat::getLevelFormula(std::shared_ptr player, const std::shared_ptr wheelSpell, const CombatDamage &damage) const { +int32_t Combat::getLevelFormula(const std::shared_ptr &player, const std::shared_ptr &wheelSpell, const CombatDamage &damage) const { if (!player) { return 0; } @@ -43,7 +50,7 @@ int32_t Combat::getLevelFormula(std::shared_ptr player, const std::share return levelFormula; } -CombatDamage Combat::getCombatDamage(std::shared_ptr creature, std::shared_ptr target) const { +CombatDamage Combat::getCombatDamage(const std::shared_ptr &creature, const std::shared_ptr &target) const { CombatDamage damage; damage.origin = params.origin; damage.primary.type = params.combatType; @@ -66,7 +73,7 @@ CombatDamage Combat::getCombatDamage(std::shared_ptr creature, std::sh int32_t min, max; if (creature->getCombatValues(min, max)) { damage.primary.value = normal_random(min, max); - } else if (std::shared_ptr player = creature->getPlayer()) { + } else if (const auto &player = creature->getPlayer()) { if (params.valueCallback) { params.valueCallback->getMinMaxValues(player, damage, params.useCharges); } else if (formulaType == COMBAT_FORMULA_LEVELMAGIC) { @@ -76,8 +83,8 @@ CombatDamage Combat::getCombatDamage(std::shared_ptr creature, std::sh static_cast(levelFormula * maxa + maxb) ); } else if (formulaType == COMBAT_FORMULA_SKILL) { - std::shared_ptr tool = player->getWeapon(); - const WeaponShared_ptr weapon = g_weapons().getWeapon(tool); + const auto &tool = player->getWeapon(); + const WeaponShared_ptr &weapon = g_weapons().getWeapon(tool); if (weapon) { damage.primary.value = normal_random( static_cast(minb), @@ -184,7 +191,7 @@ ConditionType_t Combat::DamageToConditionType(CombatType_t type) { } } -bool Combat::isPlayerCombat(std::shared_ptr target) { +bool Combat::isPlayerCombat(const std::shared_ptr &target) { if (target->getPlayer()) { return true; } @@ -196,7 +203,7 @@ bool Combat::isPlayerCombat(std::shared_ptr target) { return false; } -ReturnValue Combat::canTargetCreature(std::shared_ptr player, std::shared_ptr target) { +ReturnValue Combat::canTargetCreature(const std::shared_ptr &player, const std::shared_ptr &target) { if (player == target) { return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; } @@ -241,10 +248,10 @@ ReturnValue Combat::canTargetCreature(std::shared_ptr player, std::share } } - return Combat::canDoCombat(player, target, true); + return canDoCombat(player, target, true); } -ReturnValue Combat::canDoCombat(std::shared_ptr caster, std::shared_ptr tile, bool aggressive) { +ReturnValue Combat::canDoCombat(const std::shared_ptr &caster, const std::shared_ptr &tile, bool aggressive) { if (tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { return RETURNVALUE_NOTENOUGHROOM; } @@ -269,7 +276,7 @@ ReturnValue Combat::canDoCombat(std::shared_ptr caster, std::shared_pt return RETURNVALUE_FIRSTGOUPSTAIRS; } - if (std::shared_ptr player = caster->getPlayer()) { + if (const auto &player = caster->getPlayer()) { if (player->hasFlag(PlayerFlags_t::IgnoreProtectionZone)) { return RETURNVALUE_NOERROR; } @@ -282,11 +289,11 @@ ReturnValue Combat::canDoCombat(std::shared_ptr caster, std::shared_pt return ret; } -bool Combat::isInPvpZone(std::shared_ptr attacker, std::shared_ptr target) { +bool Combat::isInPvpZone(const std::shared_ptr &attacker, const std::shared_ptr &target) { return attacker->getZoneType() == ZONE_PVP && target->getZoneType() == ZONE_PVP; } -bool Combat::isProtected(std::shared_ptr attacker, std::shared_ptr target) { +bool Combat::isProtected(const std::shared_ptr &attacker, const std::shared_ptr &target) { uint32_t protectionLevel = g_configManager().getNumber(PROTECTION_LEVEL); if (target->getLevel() < protectionLevel || attacker->getLevel() < protectionLevel) { return true; @@ -303,33 +310,33 @@ bool Combat::isProtected(std::shared_ptr attacker, std::shared_ptr attacker, std::shared_ptr target, bool aggressive) { +ReturnValue Combat::canDoCombat(const std::shared_ptr &attacker, const std::shared_ptr &target, bool aggressive) { if (!aggressive) { return RETURNVALUE_NOERROR; } - auto targetPlayer = target ? target->getPlayer() : nullptr; + const auto &targetPlayer = target ? target->getPlayer() : nullptr; if (target) { - std::shared_ptr tile = target->getTile(); + const std::shared_ptr &tile = target->getTile(); if (tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { return RETURNVALUE_NOTENOUGHROOM; } - if (tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - auto permittedOnPz = targetPlayer ? targetPlayer->hasPermittedConditionInPZ() : false; + if (targetPlayer && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { + const auto permittedOnPz = targetPlayer->hasPermittedConditionInPZ(); return permittedOnPz ? RETURNVALUE_NOERROR : RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE; } } if (attacker) { - const std::shared_ptr attackerMaster = attacker->getMaster(); + const auto &attackerMaster = attacker->getMaster(); + const auto &attackerPlayer = attacker->getPlayer(); if (targetPlayer) { if (targetPlayer->hasFlag(PlayerFlags_t::CannotBeAttacked)) { return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; } - const std::shared_ptr targetPlayerTile = targetPlayer->getTile(); - - if (const std::shared_ptr attackerPlayer = attacker->getPlayer()) { + const auto &targetPlayerTile = targetPlayer->getTile(); + if (attackerPlayer) { if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackPlayer)) { return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; } @@ -339,7 +346,7 @@ ReturnValue Combat::canDoCombat(std::shared_ptr attacker, std::shared_ } // nopvp-zone - auto attackerTile = attackerPlayer->getTile(); + const auto &attackerTile = attackerPlayer->getTile(); if (targetPlayerTile && targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) { return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; } else if (attackerTile && attackerTile->hasFlag(TILESTATE_NOPVPZONE) && targetPlayerTile && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE | TILESTATE_PROTECTIONZONE)) { @@ -352,7 +359,7 @@ ReturnValue Combat::canDoCombat(std::shared_ptr attacker, std::shared_ } if (attackerMaster) { - if (const std::shared_ptr masterAttackerPlayer = attackerMaster->getPlayer()) { + if (const auto &masterAttackerPlayer = attackerMaster->getPlayer()) { if (masterAttackerPlayer->hasFlag(PlayerFlags_t::CannotAttackPlayer)) { return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; } @@ -377,7 +384,7 @@ ReturnValue Combat::canDoCombat(std::shared_ptr attacker, std::shared_ return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } - if (const std::shared_ptr attackerPlayer = attacker->getPlayer()) { + if (attackerPlayer) { if (attackerPlayer->hasFlag(PlayerFlags_t::CannotAttackMonster)) { return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; } @@ -386,7 +393,7 @@ ReturnValue Combat::canDoCombat(std::shared_ptr attacker, std::shared_ return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; } } else if (attacker->getMonster()) { - const std::shared_ptr targetMaster = target->getMaster(); + const auto &targetMaster = target->getMaster(); if ((!targetMaster || !targetMaster->getPlayer()) && attacker->getFaction() == FACTION_DEFAULT) { if (!attackerMaster || !attackerMaster->getPlayer()) { @@ -429,6 +436,14 @@ void Combat::setPlayerCombatValues(formulaType_t newFormulaType, double newMina, this->maxb = newMaxb; } +void Combat::postCombatEffects(const std::shared_ptr &caster, const Position &origin, const Position &pos) const { + postCombatEffects(caster, origin, pos, params); +} + +void Combat::setOrigin(CombatOrigin origin) { + params.origin = origin; +} + bool Combat::setParam(CombatParam_t param, uint32_t value) { switch (param) { case COMBAT_PARAM_TYPE: { @@ -499,6 +514,18 @@ bool Combat::setParam(CombatParam_t param, uint32_t value) { return false; } +void Combat::setArea(std::unique_ptr &newArea) { + this->area = std::move(newArea); +} + +bool Combat::hasArea() const { + return area != nullptr; +} + +void Combat::addCondition(const std::shared_ptr &condition) { + params.conditionList.emplace_back(condition); +} + bool Combat::setCallback(CallBackParam_t key) { switch (key) { case CALLBACK_PARAM_LEVELMAGICVALUE: { @@ -540,7 +567,7 @@ void Combat::setChainCallback(uint8_t chainTargets, uint8_t chainDistance, bool g_logger().trace("ChainCallback created: {}, with targets: {}, distance: {}, backtracking: {}", params.chainCallback != nullptr, chainTargets, chainDistance, backtracking); } -CallBack* Combat::getCallback(CallBackParam_t key) { +CallBack* Combat::getCallback(CallBackParam_t key) const { switch (key) { case CALLBACK_PARAM_LEVELMAGICVALUE: case CALLBACK_PARAM_SKILLVALUE: { @@ -566,7 +593,7 @@ CallBack* Combat::getCallback(CallBackParam_t key) { return nullptr; } -void Combat::CombatHealthFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data) { +void Combat::CombatHealthFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data) { if (!data) { g_logger().error("[{}]: CombatDamage is nullptr", __FUNCTION__); return; @@ -600,7 +627,7 @@ void Combat::CombatHealthFunc(std::shared_ptr caster, std::shared_ptr< g_logger().trace("[{}] (new) eventcallback: 'creatureOnCombat', damage primary: '{}', secondary: '{}'", __FUNCTION__, damage.primary.value, damage.secondary.value); if (attackerPlayer) { - std::shared_ptr item = attackerPlayer->getWeapon(); + const auto &item = attackerPlayer->getWeapon(); damage = applyImbuementElementalDamage(attackerPlayer, item, damage); g_events().eventPlayerOnCombat(attackerPlayer, target, item, damage); g_callbacks().executeCallback(EventCallback_t::playerOnCombat, &EventCallback::playerOnCombat, attackerPlayer, target, item, std::ref(damage)); @@ -624,7 +651,7 @@ void Combat::CombatHealthFunc(std::shared_ptr caster, std::shared_ptr< // Player attacking monster if (attackerPlayer && targetMonster) { - const std::unique_ptr &slot = attackerPlayer->getPreyWithMonster(targetMonster->getRaceId()); + const auto &slot = attackerPlayer->getPreyWithMonster(targetMonster->getRaceId()); if (slot && slot->isOccupied() && slot->bonus == PreyBonus_Damage && slot->bonusTimeLeft > 0) { damage.primary.value += static_cast(std::ceil((damage.primary.value * slot->bonusPercentage) / 100)); damage.secondary.value += static_cast(std::ceil((damage.secondary.value * slot->bonusPercentage) / 100)); @@ -636,7 +663,7 @@ void Combat::CombatHealthFunc(std::shared_ptr caster, std::shared_ptr< // Monster attacking player if (attackerMonster && targetPlayer) { - const std::unique_ptr &slot = targetPlayer->getPreyWithMonster(attackerMonster->getRaceId()); + const auto &slot = targetPlayer->getPreyWithMonster(attackerMonster->getRaceId()); if (slot && slot->isOccupied() && slot->bonus == PreyBonus_Defense && slot->bonusTimeLeft > 0) { damage.primary.value -= static_cast(std::ceil((damage.primary.value * slot->bonusPercentage) / 100)); damage.secondary.value -= static_cast(std::ceil((damage.secondary.value * slot->bonusPercentage) / 100)); @@ -649,7 +676,7 @@ void Combat::CombatHealthFunc(std::shared_ptr caster, std::shared_ptr< } } -CombatDamage Combat::applyImbuementElementalDamage(std::shared_ptr attackerPlayer, std::shared_ptr item, CombatDamage damage) { +CombatDamage Combat::applyImbuementElementalDamage(const std::shared_ptr &attackerPlayer, std::shared_ptr item, CombatDamage damage) { if (!item) { return damage; } @@ -691,7 +718,7 @@ CombatDamage Combat::applyImbuementElementalDamage(std::shared_ptr attac return damage; } -void Combat::CombatManaFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data) { +void Combat::CombatManaFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data) { if (!data) { g_logger().error("[{}]: CombatDamage is nullptr", __FUNCTION__); return; @@ -710,7 +737,7 @@ void Combat::CombatManaFunc(std::shared_ptr caster, std::shared_ptr player) { +bool Combat::checkFearConditionAffected(const std::shared_ptr &player) { if (player->isImmuneFear()) { return false; } @@ -719,7 +746,7 @@ bool Combat::checkFearConditionAffected(std::shared_ptr player) { return false; } - auto party = player->getParty(); + const auto &party = player->getParty(); if (party) { auto affectedCount = (party->getMemberCount() + 5) / 5; g_logger().debug("[{}] Player is member of a party, {} members can be feared", __FUNCTION__, affectedCount); @@ -738,7 +765,7 @@ bool Combat::checkFearConditionAffected(std::shared_ptr player) { return true; } -void Combat::CombatConditionFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data) { +void Combat::CombatConditionFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data) { if (params.origin == ORIGIN_MELEE && data && data->primary.value == 0 && data->secondary.value == 0) { return; } @@ -756,7 +783,7 @@ void Combat::CombatConditionFunc(std::shared_ptr caster, std::shared_p } else if (caster && caster->getMonster()) { uint16_t playerCharmRaceid = player->parseRacebyCharm(CHARM_CLEANSE, false, 0); if (playerCharmRaceid != 0) { - const auto mType = g_monsters().getMonsterType(caster->getName()); + const auto &mType = g_monsters().getMonsterType(caster->getName()); if (mType && playerCharmRaceid == mType->info.raceid) { const auto charm = g_iobestiary().getBestiaryCharm(CHARM_CLEANSE); if (charm && (charm->chance > normal_random(0, 100))) { @@ -791,18 +818,18 @@ void Combat::CombatConditionFunc(std::shared_ptr caster, std::shared_p } } -void Combat::CombatDispelFunc(std::shared_ptr, std::shared_ptr target, const CombatParams ¶ms, CombatDamage*) { +void Combat::CombatDispelFunc(const std::shared_ptr &, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage*) { if (target) { target->removeCombatCondition(params.dispelType); } } -void Combat::CombatNullFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage*) { +void Combat::CombatNullFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage*) { CombatConditionFunc(caster, target, params, nullptr); CombatDispelFunc(caster, target, params, nullptr); } -void Combat::combatTileEffects(const CreatureVector &spectators, std::shared_ptr caster, std::shared_ptr tile, const CombatParams ¶ms) { +void Combat::combatTileEffects(const CreatureVector &spectators, const std::shared_ptr &caster, const std::shared_ptr &tile, const CombatParams ¶ms) { if (params.itemId != 0) { uint16_t itemId = params.itemId; switch (itemId) { @@ -865,7 +892,7 @@ void Combat::combatTileEffects(const CreatureVector &spectators, std::shared_ptr } } - std::shared_ptr item = Item::CreateItem(itemId); + const auto &item = Item::CreateItem(itemId); if (caster) { item->setOwner(caster); } @@ -891,7 +918,7 @@ void Combat::combatTileEffects(const CreatureVector &spectators, std::shared_ptr } } -void Combat::postCombatEffects(std::shared_ptr caster, const Position &origin, const Position &pos, const CombatParams ¶ms) { +void Combat::postCombatEffects(const std::shared_ptr &caster, const Position &origin, const Position &pos, const CombatParams ¶ms) { if (caster && params.distanceEffect != CONST_ANI_NONE) { addDistanceEffect(caster, origin, pos, params.distanceEffect); } @@ -903,13 +930,13 @@ void Combat::postCombatEffects(std::shared_ptr caster, const Position } } -void Combat::addDistanceEffect(std::shared_ptr caster, const Position &fromPos, const Position &toPos, uint16_t effect) { +void Combat::addDistanceEffect(const std::shared_ptr &caster, const Position &fromPos, const Position &toPos, uint16_t effect) { if (effect == CONST_ANI_WEAPONTYPE) { if (!caster) { return; } - std::shared_ptr player = caster->getPlayer(); + const auto &player = caster->getPlayer(); if (!player) { return; } @@ -953,7 +980,7 @@ void Combat::doChainEffect(const Position &origin, const Position &dest, uint8_t fpp.maxSearchDist = 9; Position pos = origin; if (g_game().map.getPathMatching(origin, dirList, FrozenPathingConditionCall(dest), fpp)) { - for (auto dir : dirList) { + for (const auto &dir : dirList) { pos = getNextPosition(dir, pos); g_game().addMagicEffect(pos, effect); } @@ -1038,8 +1065,8 @@ void Combat::setupChain(const std::shared_ptr &weapon) { } } -bool Combat::doCombatChain(std::shared_ptr caster, std::shared_ptr target, bool aggressive) const { - metrics::method_latency measure(__METHOD_NAME__); +bool Combat::doCombatChain(const std::shared_ptr &caster, const std::shared_ptr &target, bool aggressive) const { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (!params.chainCallback) { return false; } @@ -1048,7 +1075,7 @@ bool Combat::doCombatChain(std::shared_ptr caster, std::shared_ptrgetChainValues(caster, maxTargets, chainDistance, backtracking); - auto targets = pickChainTargets(caster, params, chainDistance, maxTargets, aggressive, backtracking, std::move(target)); + auto targets = pickChainTargets(caster, params, chainDistance, maxTargets, aggressive, backtracking, target); g_logger().debug("[{}] Chain targets: {}", __FUNCTION__, targets.size()); if (targets.empty() || (targets.size() == 1 && targets.begin()->second.empty())) { @@ -1057,19 +1084,19 @@ bool Combat::doCombatChain(std::shared_ptr caster, std::shared_ptr(50, g_configManager().getNumber(COMBAT_CHAIN_DELAY)); ++i; - for (auto to : toVector) { - auto nextTarget = g_game().getCreatureByID(to); + for (const auto &to : toVector) { + const auto &nextTarget = g_game().getCreatureByID(to); if (!nextTarget) { continue; } g_dispatcher().scheduleEvent( delay, [combat, caster, nextTarget, from, affected]() { if (combat && caster && nextTarget) { - combat->doChainEffect(from, nextTarget->getPosition(), combat->params.chainEffect); + Combat::doChainEffect(from, nextTarget->getPosition(), combat->params.chainEffect); combat->doCombat(caster, nextTarget, from, affected); } }, @@ -1081,7 +1108,7 @@ bool Combat::doCombatChain(std::shared_ptr caster, std::shared_ptr caster, std::shared_ptr target) const { +bool Combat::doCombat(const std::shared_ptr &caster, const std::shared_ptr &target) const { if (caster != nullptr && params.chainCallback) { return doCombatChain(caster, target, params.aggressive); } @@ -1089,7 +1116,7 @@ bool Combat::doCombat(std::shared_ptr caster, std::shared_ptrgetPosition() : Position()); } -bool Combat::doCombat(std::shared_ptr caster, std::shared_ptr target, const Position &origin, int affected /* = 1 */) const { +bool Combat::doCombat(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, int affected /* = 1 */) const { // target combat callback function if (params.combatType != COMBAT_NONE) { CombatDamage damage = getCombatDamage(caster, target); @@ -1106,7 +1133,7 @@ bool Combat::doCombat(std::shared_ptr caster, std::shared_ptr caster, const Position &position) const { +bool Combat::doCombat(const std::shared_ptr &caster, const Position &position) const { if (caster != nullptr && params.chainCallback) { return doCombatChain(caster, caster, params.aggressive); } @@ -1127,7 +1154,7 @@ bool Combat::doCombat(std::shared_ptr caster, const Position &position return true; } -void Combat::CombatFunc(std::shared_ptr caster, const Position &origin, const Position &pos, const std::unique_ptr &area, const CombatParams ¶ms, CombatFunction func, CombatDamage* data) { +void Combat::CombatFunc(const std::shared_ptr &caster, const Position &origin, const Position &pos, const std::unique_ptr &area, const CombatParams ¶ms, const CombatFunction &func, CombatDamage* data) { std::vector> tileList; if (caster) { @@ -1140,7 +1167,7 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin uint32_t maxY = 0; // calculate the max viewable range - for (const std::shared_ptr &tile : tileList) { + for (const auto &tile : tileList) { const Position &tilePos = tile->getPosition(); uint32_t diff = Position::getDistanceX(tilePos, pos); @@ -1158,16 +1185,16 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin const int32_t rangeY = maxY + MAP_MAX_VIEW_PORT_Y; int affected = 0; - for (const std::shared_ptr &tile : tileList) { + for (const auto &tile : tileList) { if (canDoCombat(caster, tile, params.aggressive) != RETURNVALUE_NOERROR) { continue; } if (CreatureVector* creatures = tile->getCreatures()) { - const std::shared_ptr topCreature = tile->getTopCreature(); + const auto &topCreature = tile->getTopCreature(); // A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop. CreatureVector creaturesCopy = *creatures; - for (auto &creature : creaturesCopy) { + for (const auto &creature : creaturesCopy) { if (params.targetCasterOrTopMost) { if (caster && caster->getTile() == tile) { if (creature != caster) { @@ -1210,21 +1237,21 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin // Wheel of destiny get beam affected total auto spectators = Spectators().find(pos, true, rangeX, rangeX, rangeY, rangeY); - std::shared_ptr casterPlayer = caster ? caster->getPlayer() : nullptr; + const std::shared_ptr &casterPlayer = caster ? caster->getPlayer() : nullptr; uint8_t beamAffectedTotal = casterPlayer ? casterPlayer->wheel()->getBeamAffectedTotal(tmpDamage) : 0; uint8_t beamAffectedCurrent = 0; tmpDamage.affected = affected; - for (const std::shared_ptr &tile : tileList) { + for (const auto &tile : tileList) { if (canDoCombat(caster, tile, params.aggressive) != RETURNVALUE_NOERROR) { continue; } if (CreatureVector* creatures = tile->getCreatures()) { - const std::shared_ptr topCreature = tile->getTopCreature(); + const auto &topCreature = tile->getTopCreature(); // A copy of the tile's creature list is made because modifications to this vector, such as adding or removing creatures through a Lua callback, may occur during the iteration within the for loop. CreatureVector creaturesCopy = *creatures; - for (auto &creature : creaturesCopy) { + for (const auto &creature : creaturesCopy) { if (params.targetCasterOrTopMost) { if (caster && caster->getTile() == tile) { if (creature != caster) { @@ -1254,19 +1281,14 @@ void Combat::CombatFunc(std::shared_ptr caster, const Position &origin combatTileEffects(spectators.data(), caster, tile, params); } - // Wheel of destiny update beam mastery damage - if (casterPlayer) { - casterPlayer->wheel()->updateBeamMasteryDamage(tmpDamage, beamAffectedTotal, beamAffectedCurrent); - } - postCombatEffects(caster, origin, pos, params); } -void Combat::doCombatHealth(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms) { - doCombatHealth(caster, std::move(target), caster ? caster->getPosition() : Position(), damage, params); +void Combat::doCombatHealth(const std::shared_ptr &caster, const std::shared_ptr &target, CombatDamage &damage, const CombatParams ¶ms) { + doCombatHealth(caster, target, caster ? caster->getPosition() : Position(), damage, params); } -void Combat::doCombatHealth(std::shared_ptr caster, std::shared_ptr target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms) { +void Combat::doCombatHealth(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms) { bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target, params.aggressive) == RETURNVALUE_NOERROR); if ((caster && target) && (caster == target || canCombat) @@ -1300,17 +1322,17 @@ void Combat::doCombatHealth(std::shared_ptr caster, std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { +void Combat::doCombatHealth(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { applyExtensions(caster, nullptr, damage, params); const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatHealthFunc, &damage); } -void Combat::doCombatMana(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms) { +void Combat::doCombatMana(const std::shared_ptr &caster, const std::shared_ptr &target, CombatDamage &damage, const CombatParams ¶ms) { doCombatMana(caster, target, caster ? caster->getPosition() : Position(), damage, params); } -void Combat::doCombatMana(std::shared_ptr caster, std::shared_ptr target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms) { +void Combat::doCombatMana(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms) { bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target, params.aggressive) == RETURNVALUE_NOERROR); if ((caster && target) && (caster == target || canCombat) @@ -1338,18 +1360,18 @@ void Combat::doCombatMana(std::shared_ptr caster, std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { +void Combat::doCombatMana(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { applyExtensions(caster, nullptr, damage, params); const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatManaFunc, &damage); } -void Combat::doCombatCondition(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms) { +void Combat::doCombatCondition(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms) { const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatConditionFunc, nullptr); } -void Combat::doCombatCondition(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms) { +void Combat::doCombatCondition(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms) { bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target, params.aggressive) == RETURNVALUE_NOERROR); if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) { g_game().addMagicEffect(target->getPosition(), params.impactEffect); @@ -1373,12 +1395,12 @@ void Combat::doCombatCondition(std::shared_ptr caster, std::shared_ptr } } -void Combat::doCombatDispel(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms) { +void Combat::doCombatDispel(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms) { const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatDispelFunc, nullptr); } -void Combat::doCombatDispel(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms) { +void Combat::doCombatDispel(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms) { bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target, params.aggressive) == RETURNVALUE_NOERROR); if ((caster && target) && (caster == target || canCombat) @@ -1404,11 +1426,11 @@ void Combat::doCombatDispel(std::shared_ptr caster, std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms) { +[[maybe_unused]] void Combat::doCombatDefault(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms) { doCombatDefault(caster, target, caster ? caster->getPosition() : Position(), params); } -void Combat::doCombatDefault(std::shared_ptr caster, std::shared_ptr target, const Position &origin, const CombatParams ¶ms) { +void Combat::doCombatDefault(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, const CombatParams ¶ms) { if (!params.aggressive || (caster != target && Combat::canDoCombat(caster, target, params.aggressive) == RETURNVALUE_NOERROR)) { auto spectators = Spectators().find(target->getPosition(), true); @@ -1445,9 +1467,9 @@ void Combat::setRuneSpellName(const std::string &value) { runeSpellName = value; } -std::vector>> Combat::pickChainTargets(std::shared_ptr caster, const CombatParams ¶ms, uint8_t chainDistance, uint8_t maxTargets, bool backtracking, bool aggressive, std::shared_ptr initialTarget /* = nullptr */) { +std::vector>> Combat::pickChainTargets(const std::shared_ptr &caster, const CombatParams ¶ms, uint8_t chainDistance, uint8_t maxTargets, bool backtracking, bool aggressive, const std::shared_ptr &initialTarget /* = nullptr */) { Benchmark bm_pickChain; - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (!caster) { return {}; } @@ -1457,11 +1479,11 @@ std::vector>> Combat::pickChainTargets phmap::flat_hash_set visited; if (initialTarget && initialTarget != caster) { - targets.push_back(initialTarget); + targets.emplace_back(initialTarget); visited.insert(initialTarget->getID()); - resultMap.push_back({ caster->getPosition(), { initialTarget->getID() } }); + resultMap.emplace_back(caster->getPosition(), std::vector { initialTarget->getID() }); } else { - targets.push_back(caster); + targets.emplace_back(caster); maxTargets++; } @@ -1490,25 +1512,26 @@ std::vector>> Combat::pickChainTargets } if (closestSpectator) { - g_logger().trace("[{}] closestSpectator: {}", __METHOD_NAME__, closestSpectator->getName()); + g_logger().trace("[{}] closestSpectator: {}", __FUNCTION__, closestSpectator->getName()); bool found = false; for (auto &[pos, vec] : resultMap) { if (pos == currentTarget->getPosition()) { - vec.push_back(closestSpectator->getID()); + vec.emplace_back(closestSpectator->getID()); found = true; break; } } if (!found) { - resultMap.push_back({ currentTarget->getPosition(), { closestSpectator->getID() } }); + resultMap.emplace_back(currentTarget->getPosition(), std::vector { closestSpectator->getID() }); } - targets.push_back(closestSpectator); + targets.emplace_back(closestSpectator); visited.insert(closestSpectator->getID()); continue; - } else if (backtracking) { - g_logger().debug("[{}] backtracking", __METHOD_NAME__); + } + if (backtracking) { + g_logger().debug("[{}] backtracking", __FUNCTION__); targets.pop_back(); backtrackingAttempts--; continue; @@ -1516,11 +1539,11 @@ std::vector>> Combat::pickChainTargets break; } - g_logger().debug("[{}] resultMap: {} in {} ms", __METHOD_NAME__, resultMap.size(), bm_pickChain.duration()); + g_logger().debug("[{}] resultMap: {} in {} ms", __FUNCTION__, resultMap.size(), bm_pickChain.duration()); return resultMap; } -bool Combat::isValidChainTarget(std::shared_ptr caster, std::shared_ptr currentTarget, std::shared_ptr potentialTarget, const CombatParams ¶ms, bool aggressive) { +bool Combat::isValidChainTarget(const std::shared_ptr &caster, const std::shared_ptr ¤tTarget, const std::shared_ptr &potentialTarget, const CombatParams ¶ms, bool aggressive) { bool canCombat = canDoCombat(caster, potentialTarget, aggressive) == RETURNVALUE_NOERROR; bool pick = params.chainPickerCallback ? params.chainPickerCallback->onChainCombat(caster, potentialTarget) : true; bool hasSight = g_game().isSightClear(currentTarget->getPosition(), potentialTarget->getPosition(), true); @@ -1529,7 +1552,10 @@ bool Combat::isValidChainTarget(std::shared_ptr caster, std::shared_pt //**********************************************************// -uint32_t ValueCallback::getMagicLevelSkill(std::shared_ptr player, const CombatDamage &damage) const { +ValueCallback::ValueCallback(formulaType_t initType) : + type(initType) { } + +uint32_t ValueCallback::getMagicLevelSkill(const std::shared_ptr &player, const CombatDamage &damage) const { if (!player) { return 0; } @@ -1537,9 +1563,9 @@ uint32_t ValueCallback::getMagicLevelSkill(std::shared_ptr player, const uint32_t magicLevelSkill = player->getMagicLevel(); // Wheel of destiny if (player && player->wheel()->getInstant("Runic Mastery") && damage.instantSpellName.empty()) { - const std::shared_ptr spell = g_spells().getRuneSpellByName(damage.runeSpellName); + const std::shared_ptr &spell = g_spells().getRuneSpellByName(damage.runeSpellName); // Rune conjuring spell have the same name as the rune item spell. - const std::shared_ptr conjuringSpell = g_spells().getInstantSpellByName(damage.runeSpellName); + const std::shared_ptr &conjuringSpell = g_spells().getInstantSpellByName(damage.runeSpellName); if (spell && conjuringSpell && conjuringSpell != spell && normal_random(0, 100) <= 25) { uint32_t castResult = conjuringSpell->canCast(player) ? 20 : 10; magicLevelSkill += magicLevelSkill * castResult / 100; @@ -1549,18 +1575,18 @@ uint32_t ValueCallback::getMagicLevelSkill(std::shared_ptr player, const return magicLevelSkill + player->getSpecializedMagicLevel(damage.primary.type, true); } -void ValueCallback::getMinMaxValues(std::shared_ptr player, CombatDamage &damage, bool useCharges) const { +void ValueCallback::getMinMaxValues(const std::shared_ptr &player, CombatDamage &damage, bool useCharges) const { // onGetPlayerMinMaxValues(...) - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[ValueCallback::getMinMaxValues - Player {} formula {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), fmt::underlying(type)); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return; } @@ -1587,7 +1613,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 auto &tool = player->getWeapon(); const auto &weapon = g_weapons().getWeapon(tool); int32_t attackSkill = 0; float attackFactor = 0; @@ -1604,7 +1630,7 @@ void ValueCallback::getMinMaxValues(std::shared_ptr player, CombatDamage default: { g_logger().warn("[ValueCallback::getMinMaxValues] - Unknown callback type"); - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return; } } @@ -1619,7 +1645,7 @@ void ValueCallback::getMinMaxValues(std::shared_ptr player, CombatDamage ); if (shouldCalculateSecondaryDamage) { - double factor = (double)elementAttack / (double)attackValue; // attack value here is phys dmg + element dmg + double factor = static_cast(elementAttack) / static_cast(attackValue); // attack value here is phys dmg + element dmg int32_t elementDamage = std::round(defaultDmg * factor); int32_t physDmg = std::round(defaultDmg * (1.0 - factor)); damage.primary.value = physDmg; @@ -1637,23 +1663,23 @@ void ValueCallback::getMinMaxValues(std::shared_ptr player, CombatDamage LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } //**********************************************************// -void TileCallback::onTileCombat(std::shared_ptr creature, std::shared_ptr tile) const { +void TileCallback::onTileCombat(const std::shared_ptr &creature, const std::shared_ptr &tile) const { // onTileCombat(creature, pos) - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[TileCallback::onTileCombat - Creature {} type {} on tile x: {} y: {} z: {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), fmt::underlying(type), (tile->getPosition()).getX(), (tile->getPosition()).getY(), (tile->getPosition()).getZ()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return; } @@ -1673,18 +1699,18 @@ void TileCallback::onTileCombat(std::shared_ptr creature, std::shared_ //**********************************************************// -void TargetCallback::onTargetCombat(std::shared_ptr creature, std::shared_ptr target) const { +void TargetCallback::onTargetCombat(const std::shared_ptr &creature, const std::shared_ptr &target) const { // onTargetCombat(creature, target) - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[TargetCallback::onTargetCombat - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return; } @@ -1716,11 +1742,14 @@ void TargetCallback::onTargetCombat(std::shared_ptr creature, std::sha LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } //**********************************************************// +ChainCallback::ChainCallback(const uint8_t &chainTargets, const uint8_t &chainDistance, const bool &backtracking) : + m_chainDistance(chainDistance), m_chainTargets(chainTargets), m_backtracking(backtracking) { } + void ChainCallback::getChainValues(const std::shared_ptr &creature, uint8_t &maxTargets, uint8_t &chainDistance, bool &backtracking) { if (m_fromLua) { onChainCombat(creature, maxTargets, chainDistance, backtracking); @@ -1733,18 +1762,23 @@ void ChainCallback::getChainValues(const std::shared_ptr &creature, ui backtracking = m_backtracking; } } -void ChainCallback::onChainCombat(std::shared_ptr creature, uint8_t &maxTargets, uint8_t &chainDistance, bool &backtracking) { + +void ChainCallback::setFromLua(bool fromLua) { + m_fromLua = fromLua; +} + +void ChainCallback::onChainCombat(const std::shared_ptr &creature, uint8_t &maxTargets, uint8_t &chainDistance, bool &backtracking) const { // onChainCombat(creature) - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[ChainCallback::onTargetCombat - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return; } @@ -1772,21 +1806,21 @@ void ChainCallback::onChainCombat(std::shared_ptr creature, uint8_t &m LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -bool ChainPickerCallback::onChainCombat(std::shared_ptr creature, std::shared_ptr target) const { +bool ChainPickerCallback::onChainCombat(const std::shared_ptr &creature, const std::shared_ptr &target) const { // onChainCombat(creature, target) - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[ChainPickerCallback::onTargetCombat - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return true; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return true; } @@ -1821,7 +1855,7 @@ bool ChainPickerCallback::onChainCombat(std::shared_ptr creature, std: LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return result; } @@ -1831,6 +1865,10 @@ void AreaCombat::clear() { std::ranges::fill(areas, nullptr); } +std::unique_ptr AreaCombat::clone() const { + return std::make_unique(*this); +} + AreaCombat::AreaCombat(const AreaCombat &rhs) { hasExtArea = rhs.hasExtArea; for (uint_fast8_t i = 0; i <= Direction::DIRECTION_LAST; ++i) { @@ -1840,6 +1878,10 @@ AreaCombat::AreaCombat(const AreaCombat &rhs) { } } +AreaCombat::~AreaCombat() { + clear(); +} + void AreaCombat::getList(const Position ¢erPos, const Position &targetPos, std::vector> &list) const { const std::unique_ptr &area = getArea(centerPos, targetPos); if (!area) { @@ -1935,8 +1977,8 @@ void AreaCombat::copyArea(const std::unique_ptr &input, const std::u int32_t newY = y - centerY; // perform rotation - int32_t rotatedX = static_cast(round(newX * a + newY * b)); - int32_t rotatedY = static_cast(round(newX * c + newY * d)); + auto rotatedX = static_cast(round(newX * a + newY * b)); + auto rotatedY = static_cast(round(newX * c + newY * d)); // write in the output matrix using rotated coordinates (*output)[rotatedY + rotateCenterY][rotatedX + rotateCenterX] = (*input)[y][x]; @@ -1947,6 +1989,36 @@ void AreaCombat::copyArea(const std::unique_ptr &input, const std::u } } +const std::unique_ptr &AreaCombat::getArea(const Position ¢erPos, const Position &targetPos) const { + int32_t dx = Position::getOffsetX(targetPos, centerPos); + int32_t dy = Position::getOffsetY(targetPos, centerPos); + + Direction dir; + if (dx < 0) { + dir = DIRECTION_WEST; + } else if (dx > 0) { + dir = DIRECTION_EAST; + } else if (dy < 0) { + dir = DIRECTION_NORTH; + } else { + dir = DIRECTION_SOUTH; + } + + if (hasExtArea) { + if (dx < 0 && dy < 0) { + dir = DIRECTION_NORTHWEST; + } else if (dx > 0 && dy < 0) { + dir = DIRECTION_NORTHEAST; + } else if (dx < 0 && dy > 0) { + dir = DIRECTION_SOUTHWEST; + } else if (dx > 0 && dy > 0) { + dir = DIRECTION_SOUTHEAST; + } + } + + return areas[dir]; +} + std::unique_ptr AreaCombat::createArea(const std::list &list, uint32_t rows) { uint32_t cols; if (rows == 0) { @@ -1979,7 +2051,7 @@ std::unique_ptr AreaCombat::createArea(const std::list &li return area; } -void AreaCombat::setupArea(const std::list &list, uint32_t rows) { +void AreaCombat::setupArea(const std::list &list, const uint32_t rows) { auto northArea = createArea(list, rows); const uint32_t maxOutput = std::max(northArea->getCols(), northArea->getRows()) * 2; @@ -2017,11 +2089,11 @@ void AreaCombat::setupArea(int32_t length, int32_t spread) { for (int32_t x = 1; x <= cols; ++x) { if (y == rows && x == ((cols - (cols % 2)) / 2) + 1) { - list.push_back(3); + list.emplace_back(3); } else if (x >= mincol && x <= maxcol) { - list.push_back(1); + list.emplace_back(1); } else { - list.push_back(0); + list.emplace_back(0); } } @@ -2055,11 +2127,11 @@ void AreaCombat::setupArea(int32_t radius) { for (auto &row : area) { for (int cell : row) { if (cell == 1) { - list.push_back(3); + list.emplace_back(3); } else if (cell > 0 && cell <= radius) { - list.push_back(1); + list.emplace_back(1); } else { - list.push_back(0); + list.emplace_back(0); } } } @@ -2111,17 +2183,17 @@ void MagicField::onStepInField(const std::shared_ptr &creature) { const ItemType &it = items[getID()]; if (it.conditionDamage) { - auto conditionCopy = it.conditionDamage->clone(); + const auto &conditionCopy = it.conditionDamage->clone(); auto ownerId = getOwnerId(); if (ownerId) { bool harmfulField = true; - auto itemTile = getTile(); + const auto &itemTile = getTile(); if (g_game().getWorldType() == WORLD_TYPE_NO_PVP || (itemTile && itemTile->hasFlag(TILESTATE_NOPVPZONE))) { - auto ownerPlayer = g_game().getPlayerByGUID(ownerId); + const auto &ownerPlayer = g_game().getPlayerByGUID(ownerId); if (ownerPlayer) { harmfulField = false; } - auto ownerCreature = g_game().getCreatureByID(ownerId); + const auto &ownerCreature = g_game().getCreatureByID(ownerId); if (ownerCreature) { if (ownerCreature->getPlayer() || (ownerCreature->isSummon() && ownerCreature->getMaster()->getPlayer())) { harmfulField = false; @@ -2129,9 +2201,9 @@ void MagicField::onStepInField(const std::shared_ptr &creature) { } } - std::shared_ptr targetPlayer = creature->getPlayer(); + const auto &targetPlayer = creature->getPlayer(); if (targetPlayer) { - const std::shared_ptr attackerPlayer = g_game().getPlayerByID(ownerId); + const auto &attackerPlayer = g_game().getPlayerByID(ownerId); if (attackerPlayer) { if (Combat::isProtected(attackerPlayer, targetPlayer)) { harmfulField = false; @@ -2148,8 +2220,8 @@ void MagicField::onStepInField(const std::shared_ptr &creature) { } } -void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms) { - metrics::method_latency measure(__METHOD_NAME__); +void Combat::applyExtensions(const std::shared_ptr &caster, const std::shared_ptr &target, CombatDamage &damage, const CombatParams ¶ms) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (damage.extension || !caster || damage.primary.type == COMBAT_HEALING) { return; } @@ -2159,15 +2231,15 @@ void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptrgetPlayer(); - auto monster = caster->getMonster(); + const auto &player = caster->getPlayer(); + const auto &monster = caster->getMonster(); if (player) { chance = player->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE); bonus = player->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE); if (target && target->getMonster()) { uint16_t playerCharmRaceid = player->parseRacebyCharm(CHARM_LOW, false, 0); if (playerCharmRaceid != 0) { - const auto mType = g_monsters().getMonsterType(target->getName()); + const auto &mType = g_monsters().getMonsterType(target->getName()); if (mType && playerCharmRaceid == mType->info.raceid) { const auto charm = g_iobestiary().getBestiaryCharm(CHARM_LOW); if (charm) { @@ -2183,7 +2255,7 @@ void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptr(bonus) / 10000; - chance += (uint16_t)damage.criticalChance; + chance += static_cast(damage.criticalChance); if (chance != 0 && uniform_random(1, 10000) <= chance) { damage.critical = true; @@ -2193,10 +2265,10 @@ void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptrgetInventoryItem(CONST_SLOT_LEFT); + if (const 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; + const double_t fatalChance = playerWeapon->getFatalChance(); + const 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)); @@ -2208,3 +2280,107 @@ void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptrgetAttackMultiplier(); } } + +MagicField::MagicField(uint16_t type) : + Item(type), createTime(OTSYS_TIME()) { } + +std::shared_ptr MagicField::getMagicField() { + return static_self_cast(); +} + +bool MagicField::isReplaceable() const { + return Item::items[getID()].replaceable; +} + +CombatType_t MagicField::getCombatType() const { + const ItemType &it = items[getID()]; + return it.combatType; +} + +int32_t MagicField::getDamage() const { + const ItemType &it = items[getID()]; + if (it.conditionDamage) { + return it.conditionDamage->getTotalDamage(); + } + return 0; +} + +MatrixArea::MatrixArea(uint32_t initRows, uint32_t initCols) : + centerX(0), centerY(0), rows(initRows), cols(initCols) { + data_ = new bool*[rows]; + + for (uint32_t row = 0; row < rows; ++row) { + data_[row] = new bool[cols]; + + for (uint32_t col = 0; col < cols; ++col) { + data_[row][col] = false; + } + } +} + +MatrixArea::MatrixArea(const MatrixArea &rhs) { + centerX = rhs.centerX; + centerY = rhs.centerY; + rows = rhs.rows; + cols = rhs.cols; + + data_ = new bool*[rows]; + + for (uint32_t row = 0; row < rows; ++row) { + data_[row] = new bool[cols]; + + for (uint32_t col = 0; col < cols; ++col) { + data_[row][col] = rhs.data_[row][col]; + } + } +} + +MatrixArea::~MatrixArea() { + for (uint32_t row = 0; row < rows; ++row) { + delete[] data_[row]; + } + + delete[] data_; +} + +std::unique_ptr MatrixArea::clone() const { + return std::make_unique(*this); +} + +void MatrixArea::setValue(uint32_t row, uint32_t col, bool value) const { + if (row < rows && col < cols) { + data_[row][col] = value; + } else { + g_logger().error("[{}] Access exceeds the upper limit of memory block"); + throw std::out_of_range("Access exceeds the upper limit of memory block"); + } +} + +bool MatrixArea::getValue(uint32_t row, uint32_t col) const { + return data_[row][col]; +} + +void MatrixArea::setCenter(uint32_t y, uint32_t x) { + centerX = x; + centerY = y; +} + +void MatrixArea::getCenter(uint32_t &y, uint32_t &x) const { + x = centerX; + y = centerY; +} + +uint32_t MatrixArea::getRows() const { + return rows; +} + +uint32_t MatrixArea::getCols() const { + return cols; +} +const bool* MatrixArea::operator[](uint32_t i) const { + return data_[i]; +} + +bool* MatrixArea::operator[](uint32_t i) { + return data_[i]; +} diff --git a/src/creatures/combat/combat.hpp b/src/creatures/combat/combat.hpp index 304a709135d..1b8af711235 100644 --- a/src/creatures/combat/combat.hpp +++ b/src/creatures/combat/combat.hpp @@ -9,24 +9,23 @@ #pragma once +#include "items/item.hpp" #include "lua/global/baseevents.hpp" -#include "creatures/combat/condition.hpp" -#include "declarations.hpp" -#include "map/map.hpp" class Condition; class Creature; -class Item; class Spell; class Player; class MatrixArea; class Weapon; +class Tile; + +using CreatureVector = std::vector>; // for luascript callback class ValueCallback final : public CallBack { public: - explicit ValueCallback(formulaType_t initType) : - type(initType) { } + explicit ValueCallback(formulaType_t initType); /** * @brief Get the magic level skill for the player. @@ -35,42 +34,39 @@ class ValueCallback final : public CallBack { * @param damage The combat damage information. * @return The magic level skill of the player. */ - uint32_t getMagicLevelSkill(std::shared_ptr player, const CombatDamage &damage) const; - void getMinMaxValues(std::shared_ptr player, CombatDamage &damage, bool useCharges) const; + uint32_t getMagicLevelSkill(const std::shared_ptr &player, const CombatDamage &damage) const; + void getMinMaxValues(const std::shared_ptr &player, CombatDamage &damage, bool useCharges) const; private: - formulaType_t type; + formulaType_t type {}; }; class TileCallback final : public CallBack { public: - void onTileCombat(std::shared_ptr creature, std::shared_ptr tile) const; + void onTileCombat(const std::shared_ptr &creature, const std::shared_ptr &tile) const; protected: - formulaType_t type; + formulaType_t type {}; }; class TargetCallback final : public CallBack { public: - void onTargetCombat(std::shared_ptr creature, std::shared_ptr target) const; + void onTargetCombat(const std::shared_ptr &creature, const std::shared_ptr &target) const; protected: - formulaType_t type; + formulaType_t type {}; }; class ChainCallback final : public CallBack { public: ChainCallback() = default; - ChainCallback(uint8_t &chainTargets, uint8_t &chainDistance, bool &backtracking) : - m_chainDistance(chainDistance), m_chainTargets(chainTargets), m_backtracking(backtracking) { } + ChainCallback(const uint8_t &chainTargets, const uint8_t &chainDistance, const bool &backtracking); void getChainValues(const std::shared_ptr &creature, uint8_t &maxTargets, uint8_t &chainDistance, bool &backtracking); - void setFromLua(bool fromLua) { - m_fromLua = fromLua; - } + void setFromLua(bool fromLua); private: - void onChainCombat(std::shared_ptr creature, uint8_t &chainTargets, uint8_t &chainDistance, bool &backtracking); + void onChainCombat(const std::shared_ptr &creature, uint8_t &chainTargets, uint8_t &chainDistance, bool &backtracking) const; uint8_t m_chainDistance = 0; uint8_t m_chainTargets = 0; @@ -80,7 +76,7 @@ class ChainCallback final : public CallBack { class ChainPickerCallback final : public CallBack { public: - bool onChainCombat(std::shared_ptr creature, std::shared_ptr target) const; + bool onChainCombat(const std::shared_ptr &creature, const std::shared_ptr &target) const; }; struct CombatParams { @@ -117,85 +113,28 @@ using CombatFunction = std::function, std::shared class MatrixArea { public: - MatrixArea(uint32_t initRows, uint32_t initCols) : - centerX(0), centerY(0), rows(initRows), cols(initCols) { - data_ = new bool*[rows]; - - for (uint32_t row = 0; row < rows; ++row) { - data_[row] = new bool[cols]; - - for (uint32_t col = 0; col < cols; ++col) { - data_[row][col] = false; - } - } - } + MatrixArea(uint32_t initRows, uint32_t initCols); - MatrixArea(const MatrixArea &rhs) { - centerX = rhs.centerX; - centerY = rhs.centerY; - rows = rhs.rows; - cols = rhs.cols; + MatrixArea(const MatrixArea &rhs); - data_ = new bool*[rows]; + ~MatrixArea(); - for (uint32_t row = 0; row < rows; ++row) { - data_[row] = new bool[cols]; + std::unique_ptr clone() const; - for (uint32_t col = 0; col < cols; ++col) { - data_[row][col] = rhs.data_[row][col]; - } - } - } - - ~MatrixArea() { - for (uint32_t row = 0; row < rows; ++row) { - delete[] data_[row]; - } + // non-assignable + MatrixArea &operator=(const MatrixArea &) = delete; - delete[] data_; - } + void setValue(uint32_t row, uint32_t col, bool value) const; + bool getValue(uint32_t row, uint32_t col) const; - std::unique_ptr clone() const { - return std::make_unique(*this); - } + void setCenter(uint32_t y, uint32_t x); + void getCenter(uint32_t &y, uint32_t &x) const; - // non-assignable - MatrixArea &operator=(const MatrixArea &) = delete; + uint32_t getRows() const; + uint32_t getCols() const; - void setValue(uint32_t row, uint32_t col, bool value) { - if (row < rows && col < cols) { - data_[row][col] = value; - } else { - g_logger().error("[{}] Access exceeds the upper limit of memory block"); - throw std::out_of_range("Access exceeds the upper limit of memory block"); - } - } - bool getValue(uint32_t row, uint32_t col) const { - return data_[row][col]; - } - - void setCenter(uint32_t y, uint32_t x) { - centerX = x; - centerY = y; - } - void getCenter(uint32_t &y, uint32_t &x) const { - x = centerX; - y = centerY; - } - - uint32_t getRows() const { - return rows; - } - uint32_t getCols() const { - return cols; - } - - const bool* operator[](uint32_t i) const { - return data_[i]; - } - bool* operator[](uint32_t i) { - return data_[i]; - } + const bool* operator[](uint32_t i) const; + bool* operator[](uint32_t i); private: uint32_t centerX; @@ -211,9 +150,7 @@ class AreaCombat { AreaCombat() = default; AreaCombat(const AreaCombat &rhs); - ~AreaCombat() { - clear(); - } + ~AreaCombat(); // non-assignable AreaCombat &operator=(const AreaCombat &) = delete; @@ -226,43 +163,13 @@ class AreaCombat { void setupExtArea(const std::list &list, uint32_t rows); void clear(); - std::unique_ptr clone() const { - return std::make_unique(*this); - } + std::unique_ptr clone() const; private: std::unique_ptr createArea(const std::list &list, uint32_t rows); void copyArea(const std::unique_ptr &input, const std::unique_ptr &output, MatrixOperation_t op) const; - const std::unique_ptr &getArea(const Position ¢erPos, const Position &targetPos) const { - int32_t dx = Position::getOffsetX(targetPos, centerPos); - int32_t dy = Position::getOffsetY(targetPos, centerPos); - - Direction dir; - if (dx < 0) { - dir = DIRECTION_WEST; - } else if (dx > 0) { - dir = DIRECTION_EAST; - } else if (dy < 0) { - dir = DIRECTION_NORTH; - } else { - dir = DIRECTION_SOUTH; - } - - if (hasExtArea) { - if (dx < 0 && dy < 0) { - dir = DIRECTION_NORTHWEST; - } else if (dx > 0 && dy < 0) { - dir = DIRECTION_NORTHEAST; - } else if (dx < 0 && dy > 0) { - dir = DIRECTION_SOUTHWEST; - } else if (dx > 0 && dy > 0) { - dir = DIRECTION_SOUTHEAST; - } - } - - return areas[dir]; - } + const std::unique_ptr &getArea(const Position ¢erPos, const Position &targetPos) const; std::array, Direction::DIRECTION_LAST + 1> areas {}; bool hasExtArea = false; @@ -276,60 +183,50 @@ 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 applyExtensions(const std::shared_ptr &caster, const 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); + static void doCombatHealth(const std::shared_ptr &caster, const std::shared_ptr &target, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatHealth(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms); - static void doCombatMana(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms); - static void doCombatMana(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatMana(const std::shared_ptr &caster, const std::shared_ptr &target, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatMana(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms); - static void doCombatCondition(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms); - static void doCombatCondition(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms); + static void doCombatCondition(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms); + static void doCombatCondition(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms); - static void doCombatDispel(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms); - static void doCombatDispel(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms); + static void doCombatDispel(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms); + static void doCombatDispel(const std::shared_ptr &caster, const Position &position, const std::unique_ptr &area, const CombatParams ¶ms); static void getCombatArea(const Position ¢erPos, const Position &targetPos, const std::unique_ptr &area, std::vector> &list); - static bool isInPvpZone(std::shared_ptr attacker, std::shared_ptr target); - static bool isProtected(std::shared_ptr attacker, std::shared_ptr target); - static bool isPlayerCombat(std::shared_ptr target); + static bool isInPvpZone(const std::shared_ptr &attacker, const std::shared_ptr &target); + static bool isProtected(const std::shared_ptr &attacker, const std::shared_ptr &target); + static bool isPlayerCombat(const std::shared_ptr &target); static CombatType_t ConditionToDamageType(ConditionType_t type); static ConditionType_t DamageToConditionType(CombatType_t type); - static ReturnValue canTargetCreature(std::shared_ptr attacker, std::shared_ptr target); - static ReturnValue canDoCombat(std::shared_ptr caster, std::shared_ptr tile, bool aggressive); - static ReturnValue canDoCombat(std::shared_ptr attacker, std::shared_ptr target, bool aggressive); - static void postCombatEffects(std::shared_ptr caster, const Position &origin, const Position &pos, const CombatParams ¶ms); + static ReturnValue canTargetCreature(const std::shared_ptr &attacker, const std::shared_ptr &target); + static ReturnValue canDoCombat(const std::shared_ptr &caster, const std::shared_ptr &tile, bool aggressive); + static ReturnValue canDoCombat(const std::shared_ptr &attacker, const std::shared_ptr &target, bool aggressive); + static void postCombatEffects(const std::shared_ptr &caster, const Position &origin, const Position &pos, const CombatParams ¶ms); - static void addDistanceEffect(std::shared_ptr caster, const Position &fromPos, const Position &toPos, uint16_t effect); + static void addDistanceEffect(const std::shared_ptr &caster, const Position &fromPos, const Position &toPos, uint16_t effect); - bool doCombat(std::shared_ptr caster, std::shared_ptr target) const; - bool doCombat(std::shared_ptr caster, std::shared_ptr target, const Position &origin, int affected = 1) const; - bool doCombat(std::shared_ptr caster, const Position &pos) const; + bool doCombat(const std::shared_ptr &caster, const std::shared_ptr &target) const; + bool doCombat(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, int affected = 1) const; + bool doCombat(const std::shared_ptr &caster, const Position &pos) const; bool setCallback(CallBackParam_t key); void setChainCallback(uint8_t chainTargets, uint8_t chainDistance, bool backtracking); - CallBack* getCallback(CallBackParam_t key); + CallBack* getCallback(CallBackParam_t key) const; bool setParam(CombatParam_t param, uint32_t value); - void setArea(std::unique_ptr &newArea) { - this->area = std::move(newArea); - } - bool hasArea() const { - return area != nullptr; - } - void addCondition(const std::shared_ptr condition) { - params.conditionList.emplace_back(condition); - } + void setArea(std::unique_ptr &newArea); + bool hasArea() const; + void addCondition(const std::shared_ptr &condition); void setPlayerCombatValues(formulaType_t formulaType, double mina, double minb, double maxa, double maxb); - void postCombatEffects(std::shared_ptr caster, const Position &origin, const Position &pos) const { - postCombatEffects(std::move(caster), origin, pos, params); - } + void postCombatEffects(const std::shared_ptr &caster, const Position &origin, const Position &pos) const; - void setOrigin(CombatOrigin origin) { - params.origin = origin; - } + void setOrigin(CombatOrigin origin); /** * @brief Sets the name of the instant spell. @@ -346,24 +243,24 @@ class Combat { void setRuneSpellName(const std::string &value); void setupChain(const std::shared_ptr &weapon); - bool doCombatChain(std::shared_ptr caster, std::shared_ptr target, bool aggressive) const; + bool doCombatChain(const std::shared_ptr &caster, const std::shared_ptr &target, bool aggressive) const; private: static void doChainEffect(const Position &origin, const Position &pos, uint8_t effect); - static std::vector>> pickChainTargets(std::shared_ptr caster, const CombatParams ¶ms, uint8_t chainDistance, uint8_t maxTargets, bool aggressive, bool backtracking, std::shared_ptr initialTarget = nullptr); - static bool isValidChainTarget(std::shared_ptr caster, std::shared_ptr currentTarget, std::shared_ptr potentialTarget, const CombatParams ¶ms, bool aggressive); + static std::vector>> pickChainTargets(const std::shared_ptr &caster, const CombatParams ¶ms, uint8_t chainDistance, uint8_t maxTargets, bool aggressive, bool backtracking, const std::shared_ptr &initialTarget = nullptr); + static bool isValidChainTarget(const std::shared_ptr &caster, const std::shared_ptr ¤tTarget, const std::shared_ptr &potentialTarget, const CombatParams ¶ms, bool aggressive); - static void doCombatDefault(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms); + static void doCombatDefault(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms); - static void doCombatHealth(std::shared_ptr caster, std::shared_ptr target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms); - static void doCombatMana(std::shared_ptr caster, std::shared_ptr target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms); - static void doCombatDefault(std::shared_ptr caster, std::shared_ptr target, const Position &origin, const CombatParams ¶ms); + static void doCombatHealth(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatMana(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatDefault(const std::shared_ptr &caster, const std::shared_ptr &target, const Position &origin, const CombatParams ¶ms); - static void CombatFunc(std::shared_ptr caster, const Position &origin, const Position &pos, const std::unique_ptr &area, const CombatParams ¶ms, CombatFunction func, CombatDamage* data); + static void CombatFunc(const std::shared_ptr &caster, const Position &origin, const Position &pos, const std::unique_ptr &area, const CombatParams ¶ms, const CombatFunction &func, CombatDamage* data); - static void CombatHealthFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data); - static CombatDamage applyImbuementElementalDamage(std::shared_ptr attackerPlayer, std::shared_ptr item, CombatDamage damage); - static void CombatManaFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* damage); + static void CombatHealthFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); + static CombatDamage applyImbuementElementalDamage(const std::shared_ptr &attackerPlayer, std::shared_ptr item, CombatDamage damage); + static void CombatManaFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* damage); /** * @brief Checks if a fear condition can be applied to a player. * @@ -378,12 +275,12 @@ class Combat { * @param player Pointer to the Player object to be checked. * @return true if the fear condition can be applied, false otherwise. */ - static bool checkFearConditionAffected(std::shared_ptr player); - static void CombatConditionFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data); - static void CombatDispelFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data); - static void CombatNullFunc(std::shared_ptr caster, std::shared_ptr target, const CombatParams ¶ms, CombatDamage* data); + static bool checkFearConditionAffected(const std::shared_ptr &player); + static void CombatConditionFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); + static void CombatDispelFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); + static void CombatNullFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); - static void combatTileEffects(const CreatureVector &spectators, std::shared_ptr caster, std::shared_ptr tile, const CombatParams ¶ms); + static void combatTileEffects(const CreatureVector &spectators, const std::shared_ptr &caster, const std::shared_ptr &tile, const CombatParams ¶ms); /** * @brief Calculate the level formula for combat. @@ -393,8 +290,8 @@ class Combat { * @param damage The combat damage. * @return The calculated level formula. */ - int32_t getLevelFormula(std::shared_ptr player, std::shared_ptr wheelSpell, const CombatDamage &damage) const; - CombatDamage getCombatDamage(std::shared_ptr creature, std::shared_ptr target) const; + int32_t getLevelFormula(const std::shared_ptr &player, const std::shared_ptr &wheelSpell, const CombatDamage &damage) const; + CombatDamage getCombatDamage(const std::shared_ptr &creature, const std::shared_ptr &target) const; // configureable CombatParams params; @@ -414,27 +311,13 @@ class Combat { class MagicField final : public Item { public: - explicit MagicField(uint16_t type) : - Item(type), createTime(OTSYS_TIME()) { } - - std::shared_ptr getMagicField() override { - return static_self_cast(); - } - - bool isReplaceable() const { - return Item::items[getID()].replaceable; - } - CombatType_t getCombatType() const { - const ItemType &it = items[getID()]; - return it.combatType; - } - int32_t getDamage() const { - const ItemType &it = items[getID()]; - if (it.conditionDamage) { - return it.conditionDamage->getTotalDamage(); - } - return 0; - } + explicit MagicField(uint16_t type); + + std::shared_ptr getMagicField() override; + + bool isReplaceable() const; + CombatType_t getCombatType() const; + int32_t getDamage() const; void onStepInField(const std::shared_ptr &creature); private: diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp index bc262a41c76..da90b03f65a 100644 --- a/src/creatures/combat/condition.cpp +++ b/src/creatures/combat/condition.cpp @@ -8,10 +8,19 @@ */ #include "creatures/combat/condition.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/combat.hpp" +#include "creatures/monsters/monsters.hpp" +#include "enums/player_icons.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "io/fileloader.hpp" +#include "kv/kv.hpp" #include "map/spectators.hpp" +#include "creatures/creature.hpp" +#include "creatures/players/player.hpp" +#include "server/network/protocol/protocolgame.hpp" /** * Condition @@ -178,7 +187,7 @@ void Condition::setTicks(int32_t newTicks) { endTime = ticks + OTSYS_TIME(); } -bool Condition::executeCondition(std::shared_ptr creature, int32_t interval) { +bool Condition::executeCondition(const std::shared_ptr &creature, int32_t interval) { if (ticks == -1) { return true; } @@ -313,6 +322,10 @@ std::shared_ptr Condition::createCondition(PropStream &propStream) { return createCondition(static_cast(id), static_cast(type), ticks, 0, buff != 0, subId); } +Condition::Condition(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, bool isPersistent) : + endTime(initTicks == -1 ? std::numeric_limits::max() : 0), + subId(initSubId), ticks(initTicks), conditionType(initType), id(initId), isBuff(initBuff), m_isPersistent(isPersistent) { } + bool Condition::startCondition(std::shared_ptr) { if (ticks > 0) { endTime = ticks + OTSYS_TIME(); @@ -368,7 +381,27 @@ std::unordered_set Condition::getIcons() const { return icons; } -bool Condition::updateCondition(const std::shared_ptr addCondition) { +ConditionId_t Condition::getId() const { + return id; +} + +uint32_t Condition::getSubId() const { + return subId; +} + +ConditionType_t Condition::getType() const { + return conditionType; +} + +int64_t Condition::getEndTime() const { + return endTime; +} + +int32_t Condition::getTicks() const { + return ticks; +} + +bool Condition::updateCondition(const std::shared_ptr &addCondition) { if (conditionType != addCondition->getType()) { return false; } @@ -388,11 +421,14 @@ bool Condition::updateCondition(const std::shared_ptr addCondition) { * ConditionGeneric */ +ConditionGeneric::ConditionGeneric(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, bool isPersistent) : + Condition(initId, initType, initTicks, initBuff, initSubId, isPersistent) { } + bool ConditionGeneric::startCondition(std::shared_ptr creature) { return Condition::startCondition(creature); } -bool ConditionGeneric::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionGeneric::executeCondition(const std::shared_ptr &creature, int32_t interval) { return Condition::executeCondition(creature, interval); } @@ -452,6 +488,10 @@ std::unordered_set ConditionGeneric::getIcons() const { return icons; } +std::shared_ptr ConditionGeneric::clone() const { + return std::make_shared(*this); +} + /** * ConditionAttributes */ @@ -491,7 +531,7 @@ void ConditionAttributes::addCondition(std::shared_ptr creature, const updateCharmChanceModifier(creature); disableDefense = conditionAttrs->disableDefense; - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { updatePercentSkills(player); updateSkills(player); updatePercentStats(player); @@ -581,6 +621,9 @@ void ConditionAttributes::serialize(PropWriteStream &propWriteStream) { propWriteStream.write(charmChanceModifier); } +ConditionAttributes::ConditionAttributes(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + bool ConditionAttributes::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; @@ -595,7 +638,7 @@ bool ConditionAttributes::startCondition(std::shared_ptr creature) { updatePercentIncreases(creature); updateIncreases(creature); updateCharmChanceModifier(creature); - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { updatePercentSkills(player); updateSkills(player); updatePercentStats(player); @@ -605,7 +648,7 @@ bool ConditionAttributes::startCondition(std::shared_ptr creature) { return true; } -void ConditionAttributes::updatePercentStats(std::shared_ptr player) { +void ConditionAttributes::updatePercentStats(const std::shared_ptr &player) { for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { if (statsPercent[i] == 0) { continue; @@ -631,7 +674,7 @@ void ConditionAttributes::updatePercentStats(std::shared_ptr player) { } } -void ConditionAttributes::updateStats(std::shared_ptr player) { +void ConditionAttributes::updateStats(const std::shared_ptr &player) const { bool needUpdate = false; for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { @@ -647,9 +690,9 @@ void ConditionAttributes::updateStats(std::shared_ptr player) { } } -void ConditionAttributes::updatePercentSkills(std::shared_ptr player) { +void ConditionAttributes::updatePercentSkills(const std::shared_ptr &player) { for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - skills_t skill = static_cast(i); + auto skill = static_cast(i); if (skillsPercent[skill] == 0) { continue; } @@ -659,7 +702,7 @@ void ConditionAttributes::updatePercentSkills(std::shared_ptr player) { } } -void ConditionAttributes::updateSkills(std::shared_ptr player) { +void ConditionAttributes::updateSkills(const std::shared_ptr &player) const { bool needUpdateSkills = false; for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { @@ -674,7 +717,7 @@ void ConditionAttributes::updateSkills(std::shared_ptr player) { } } -void ConditionAttributes::updatePercentAbsorbs(std::shared_ptr creature) { +void ConditionAttributes::updatePercentAbsorbs(const std::shared_ptr &creature) { for (uint8_t i = 0; i < COMBAT_COUNT; i++) { auto value = getAbsorbPercentByIndex(i); if (value == 0) { @@ -684,7 +727,7 @@ void ConditionAttributes::updatePercentAbsorbs(std::shared_ptr creatur } } -void ConditionAttributes::updateAbsorbs(std::shared_ptr creature) const { +void ConditionAttributes::updateAbsorbs(const std::shared_ptr &creature) const { for (uint8_t i = 0; i < COMBAT_COUNT; i++) { auto value = getAbsorbByIndex(i); if (value == 0) { @@ -695,7 +738,7 @@ void ConditionAttributes::updateAbsorbs(std::shared_ptr creature) cons } } -void ConditionAttributes::updatePercentIncreases(std::shared_ptr creature) { +void ConditionAttributes::updatePercentIncreases(const std::shared_ptr &creature) { for (uint8_t i = 0; i < COMBAT_COUNT; i++) { auto increasePercentValue = getIncreasePercentById(i); if (increasePercentValue == 0) { @@ -705,7 +748,7 @@ void ConditionAttributes::updatePercentIncreases(std::shared_ptr creat } } -void ConditionAttributes::updateIncreases(std::shared_ptr creature) const { +void ConditionAttributes::updateIncreases(const std::shared_ptr &creature) const { for (uint8_t i = 0; i < COMBAT_COUNT; i++) { auto increaseValue = getIncreaseByIndex(i); if (increaseValue == 0) { @@ -715,11 +758,11 @@ void ConditionAttributes::updateIncreases(std::shared_ptr creature) co } } -void ConditionAttributes::updateCharmChanceModifier(std::shared_ptr creature) const { +void ConditionAttributes::updateCharmChanceModifier(const std::shared_ptr &creature) const { creature->setCharmChanceModifier(creature->getCharmChanceModifier() + charmChanceModifier); } -void ConditionAttributes::updatePercentBuffs(std::shared_ptr creature) { +void ConditionAttributes::updatePercentBuffs(const std::shared_ptr &creature) { for (int32_t i = BUFF_FIRST; i <= BUFF_LAST; ++i) { if (buffsPercent[i] == 0) { continue; @@ -730,7 +773,7 @@ void ConditionAttributes::updatePercentBuffs(std::shared_ptr creature) } } -void ConditionAttributes::updateBuffs(std::shared_ptr creature) { +void ConditionAttributes::updateBuffs(const std::shared_ptr &creature) const { bool needUpdate = false; for (int32_t i = BUFF_FIRST; i <= BUFF_LAST; ++i) { if (buffs[i]) { @@ -743,12 +786,12 @@ void ConditionAttributes::updateBuffs(std::shared_ptr creature) { } } -bool ConditionAttributes::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionAttributes::executeCondition(const std::shared_ptr &creature, int32_t interval) { return ConditionGeneric::executeCondition(creature, interval); } void ConditionAttributes::endCondition(std::shared_ptr creature) { - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { bool needUpdate = false; @@ -1078,6 +1121,10 @@ bool ConditionAttributes::setParam(ConditionParam_t param, int32_t value) { } } +std::shared_ptr ConditionAttributes::clone() const { + return std::make_shared(*this); +} + int32_t ConditionAttributes::getAbsorbByIndex(uint8_t index) const { try { return absorbs.at(index); @@ -1150,19 +1197,22 @@ void ConditionAttributes::setIncreasePercent(uint8_t index, int32_t value) { * ConditionRegeneration */ +ConditionRegeneration::ConditionRegeneration(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, iniTicks, initBuff, initSubId) { } + bool ConditionRegeneration::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; } - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } return true; } void ConditionRegeneration::endCondition(std::shared_ptr creature) { - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } } @@ -1171,7 +1221,7 @@ void ConditionRegeneration::addCondition(std::shared_ptr creature, con if (updateCondition(addCondition)) { setTicks(addCondition->getTicks()); - const std::shared_ptr &conditionRegen = addCondition->static_self_cast(); + const auto &conditionRegen = addCondition->static_self_cast(); healthTicks = conditionRegen->healthTicks; manaTicks = conditionRegen->manaTicks; @@ -1180,7 +1230,7 @@ void ConditionRegeneration::addCondition(std::shared_ptr creature, con manaGain = conditionRegen->manaGain; } - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } } @@ -1214,10 +1264,10 @@ void ConditionRegeneration::serialize(PropWriteStream &propWriteStream) { propWriteStream.write(manaGain); } -bool ConditionRegeneration::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionRegeneration::executeCondition(const std::shared_ptr &creature, int32_t interval) { internalHealthTicks += interval; internalManaTicks += interval; - auto player = creature->getPlayer(); + const auto &player = creature->getPlayer(); int32_t dailyStreak = 0; if (player) { dailyStreak = static_cast(player->kv()->scoped("daily-reward")->get("streak")->getNumber()); @@ -1297,8 +1347,8 @@ bool ConditionRegeneration::setParam(ConditionParam_t param, int32_t value) { } } -uint32_t ConditionRegeneration::getHealthTicks(std::shared_ptr creature) const { - std::shared_ptr player = creature->getPlayer(); +uint32_t ConditionRegeneration::getHealthTicks(const std::shared_ptr &creature) const { + const auto &player = creature->getPlayer(); if (player != nullptr && isBuff) { return healthTicks / g_configManager().getFloat(RATE_SPELL_COOLDOWN); @@ -1307,8 +1357,8 @@ uint32_t ConditionRegeneration::getHealthTicks(std::shared_ptr creatur return healthTicks; } -uint32_t ConditionRegeneration::getManaTicks(std::shared_ptr creature) const { - std::shared_ptr player = creature->getPlayer(); +uint32_t ConditionRegeneration::getManaTicks(const std::shared_ptr &creature) const { + const auto &player = creature->getPlayer(); if (player != nullptr && isBuff) { return manaTicks / g_configManager().getFloat(RATE_SPELL_COOLDOWN); @@ -1317,10 +1367,17 @@ uint32_t ConditionRegeneration::getManaTicks(std::shared_ptr creature) return manaTicks; } +std::shared_ptr ConditionRegeneration::clone() const { + return std::make_shared(*this); +} + /** * ConditionManaShield */ +ConditionManaShield::ConditionManaShield(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff, uint32_t initSubId) : + Condition(initId, initType, iniTicks, initBuff, initSubId) { } + bool ConditionManaShield::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; @@ -1329,7 +1386,7 @@ bool ConditionManaShield::startCondition(std::shared_ptr creature) { creature->setManaShield(manaShield); creature->setMaxManaShield(manaShield); - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } @@ -1339,7 +1396,7 @@ bool ConditionManaShield::startCondition(std::shared_ptr creature) { void ConditionManaShield::endCondition(std::shared_ptr creature) { creature->setManaShield(0); creature->setMaxManaShield(0); - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } } @@ -1354,7 +1411,7 @@ void ConditionManaShield::addCondition(std::shared_ptr creature, const creature->setManaShield(manaShield); creature->setMaxManaShield(manaShield); - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->sendStats(); } } @@ -1385,6 +1442,10 @@ bool ConditionManaShield::setParam(ConditionParam_t param, int32_t value) { } } +std::shared_ptr ConditionManaShield::clone() const { + return std::make_shared(*this); +} + std::unordered_set ConditionManaShield::getIcons() const { auto icons = Condition::getIcons(); if (manaShield != 0) { @@ -1399,11 +1460,14 @@ std::unordered_set ConditionManaShield::getIcons() const { * ConditionSoul */ +ConditionSoul::ConditionSoul(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, iniTicks, initBuff, initSubId) { } + void ConditionSoul::addCondition(std::shared_ptr, const std::shared_ptr addCondition) { if (updateCondition(addCondition)) { setTicks(addCondition->getTicks()); - const std::shared_ptr &conditionSoul = addCondition->static_self_cast(); + const auto &conditionSoul = addCondition->static_self_cast(); soulTicks = conditionSoul->soulTicks; soulGain = conditionSoul->soulGain; @@ -1429,10 +1493,10 @@ void ConditionSoul::serialize(PropWriteStream &propWriteStream) { propWriteStream.write(soulTicks); } -bool ConditionSoul::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionSoul::executeCondition(const std::shared_ptr &creature, int32_t interval) { internalSoulTicks += interval; - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { if (player->getZoneType() != ZONE_PROTECTION) { if (internalSoulTicks >= soulTicks) { internalSoulTicks = 0; @@ -1460,6 +1524,10 @@ bool ConditionSoul::setParam(ConditionParam_t param, int32_t value) { } } +std::shared_ptr ConditionSoul::clone() const { + return std::make_shared(*this); +} + /** * ConditionDamage */ @@ -1530,7 +1598,7 @@ bool ConditionDamage::unserializeProp(ConditionAttr_t attr, PropStream &propStre return false; } - damageList.push_back(damageInfo); + damageList.emplace_back(damageInfo); if (ticks != -1) { setTicks(ticks + damageInfo.interval); } @@ -1554,8 +1622,8 @@ void ConditionDamage::serialize(PropWriteStream &propWriteStream) { } } -bool ConditionDamage::updateCondition(const std::shared_ptr addCondition) { - const std::shared_ptr &conditionDamage = addCondition->static_self_cast(); +bool ConditionDamage::updateCondition(const std::shared_ptr &addCondition) { + const auto &conditionDamage = addCondition->static_self_cast(); if (conditionDamage->doForceUpdate()) { return true; } @@ -1588,7 +1656,7 @@ bool ConditionDamage::addDamage(int32_t rounds, int32_t time, int32_t value) { damageInfo.timeLeft = time; damageInfo.value = value; - damageList.push_back(damageInfo); + damageList.emplace_back(damageInfo); if (ticks != -1) { setTicks(ticks + damageInfo.interval); @@ -1598,6 +1666,10 @@ bool ConditionDamage::addDamage(int32_t rounds, int32_t time, int32_t value) { return true; } +bool ConditionDamage::doForceUpdate() const { + return forceUpdate; +} + bool ConditionDamage::init() { if (periodDamage != 0) { return true; @@ -1642,7 +1714,7 @@ bool ConditionDamage::startCondition(std::shared_ptr creature) { return true; } -bool ConditionDamage::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionDamage::executeCondition(const std::shared_ptr &creature, int32_t interval) { if (periodDamage != 0) { periodDamageTick += interval; @@ -1696,8 +1768,8 @@ bool ConditionDamage::getNextDamage(int32_t &damage) { return false; } -bool ConditionDamage::doDamage(std::shared_ptr creature, int32_t healthChange) { - auto attacker = g_game().getPlayerByGUID(owner) ? g_game().getPlayerByGUID(owner)->getCreature() : g_game().getCreatureByID(owner); +bool ConditionDamage::doDamage(const std::shared_ptr &creature, int32_t healthChange) const { + const auto &attacker = g_game().getPlayerByGUID(owner) ? g_game().getPlayerByGUID(owner)->getCreature() : g_game().getCreatureByID(owner); bool isPlayer = attacker && attacker->getPlayer(); if (creature->isSuppress(getType(), isPlayer)) { return true; @@ -1833,6 +1905,13 @@ std::unordered_set ConditionDamage::getIcons() const { return icons; } +std::shared_ptr ConditionDamage::clone() const { + return std::make_shared(*this); +} + +ConditionDamage::ConditionDamage(ConditionId_t intiId, ConditionType_t initType, bool initBuff, uint32_t initSubId) : + Condition(intiId, initType, 0, initBuff, initSubId) { } + void ConditionDamage::generateDamageList(int32_t amount, int32_t start, std::list &list) { amount = std::abs(amount); int32_t sum = 0; @@ -1844,7 +1923,7 @@ void ConditionDamage::generateDamageList(int32_t amount, int32_t start, std::lis do { sum += i; - list.push_back(i); + list.emplace_back(i); x1 = std::fabs(1.0 - ((static_cast(sum)) + i) / med); x2 = std::fabs(1.0 - (static_cast(sum) / med)); @@ -1855,13 +1934,13 @@ void ConditionDamage::generateDamageList(int32_t amount, int32_t start, std::lis /** * ConditionFeared */ -bool ConditionFeared::isStuck(std::shared_ptr creature, Position pos) const { +bool ConditionFeared::isStuck(const std::shared_ptr &creature, Position pos) const { return std::ranges::all_of(m_directionsVector, [&](Direction dir) { return !canWalkTo(creature, pos, dir); }); } -bool ConditionFeared::getRandomDirection(std::shared_ptr creature, Position pos) { +bool ConditionFeared::getRandomDirection(const std::shared_ptr &creature, Position pos) { static std::vector directions { DIRECTION_NORTH, DIRECTION_NORTHEAST, @@ -1887,7 +1966,7 @@ bool ConditionFeared::getRandomDirection(std::shared_ptr creature, Pos return false; } -bool ConditionFeared::canWalkTo(std::shared_ptr creature, Position pos, Direction moveDirection) const { +bool ConditionFeared::canWalkTo(const std::shared_ptr &creature, Position pos, Direction moveDirection) const { pos = getNextPosition(moveDirection, pos); if (!creature) { g_logger().error("[{}] creature is nullptr", __FUNCTION__); @@ -1896,7 +1975,7 @@ bool ConditionFeared::canWalkTo(std::shared_ptr creature, Position pos auto tile = g_game().map.getTile(pos); if (tile && tile->getTopVisibleCreature(creature) == nullptr && tile->queryAdd(0, creature, 1, FLAG_PATHFINDING) == RETURNVALUE_NOERROR) { - std::shared_ptr field = tile->getFieldItem(); + const auto &field = tile->getFieldItem(); if (field && !field->isBlocking() && field->getDamage() != 0) { return false; } @@ -1906,7 +1985,7 @@ bool ConditionFeared::canWalkTo(std::shared_ptr creature, Position pos return false; } -bool ConditionFeared::getFleeDirection(std::shared_ptr creature) { +bool ConditionFeared::getFleeDirection(const std::shared_ptr &creature) { Position creaturePos = creature->getPosition(); int_fast32_t offx = Position::getOffsetX(creaturePos, fleeingFromPos); @@ -1982,7 +2061,7 @@ bool ConditionFeared::getFleeDirection(std::shared_ptr creature) { return false; } -bool ConditionFeared::getFleePath(std::shared_ptr creature, const Position &pos, std::vector &dirList) { +bool ConditionFeared::getFleePath(const std::shared_ptr &creature, const Position &pos, std::vector &dirList) { const std::vector walkSize { 15, 9, 3, 1 }; bool found = false; std::ptrdiff_t found_size = 0; @@ -2076,6 +2155,9 @@ bool ConditionFeared::setPositionParam(ConditionParam_t param, const Position &p return false; } +ConditionFeared::ConditionFeared(ConditionId_t intiId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + Condition(intiId, initType, initTicks, initBuff, initSubId) { } + bool ConditionFeared::startCondition(std::shared_ptr creature) { g_logger().debug("[ConditionFeared::executeCondition] Condition started for {}", creature->getName()); getFleeDirection(creature); @@ -2083,7 +2165,7 @@ bool ConditionFeared::startCondition(std::shared_ptr creature) { return Condition::startCondition(creature); } -bool ConditionFeared::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionFeared::executeCondition(const std::shared_ptr &creature, int32_t interval) { Position currentPos = creature->getPosition(); std::vector listDir; @@ -2114,7 +2196,7 @@ void ConditionFeared::endCondition(std::shared_ptr creature) { /* * After a player is feared there's a 10 seconds before they can can feared again. */ - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->setImmuneFear(); } @@ -2133,6 +2215,10 @@ std::unordered_set ConditionFeared::getIcons() const { return icons; } +std::shared_ptr ConditionFeared::clone() const { + return std::make_shared(*this); +} + /** * ConditionSpeed */ @@ -2200,6 +2286,9 @@ void ConditionSpeed::serialize(PropWriteStream &propWriteStream) { propWriteStream.write(maxb); } +ConditionSpeed::ConditionSpeed(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, int32_t initChangeSpeed) : + Condition(initId, initType, initTicks, initBuff, initSubId), speedDelta(initChangeSpeed) { } + bool ConditionSpeed::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; @@ -2220,7 +2309,7 @@ bool ConditionSpeed::startCondition(std::shared_ptr creature) { return true; } -bool ConditionSpeed::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionSpeed::executeCondition(const std::shared_ptr &creature, int32_t interval) { return Condition::executeCondition(creature, interval); } @@ -2282,10 +2371,17 @@ std::unordered_set ConditionSpeed::getIcons() const { return icons; } +std::shared_ptr ConditionSpeed::clone() const { + return std::make_shared(*this); +} + /** * ConditionInvisible */ +ConditionInvisible::ConditionInvisible(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + bool ConditionInvisible::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; @@ -2301,6 +2397,10 @@ void ConditionInvisible::endCondition(std::shared_ptr creature) { } } +std::shared_ptr ConditionInvisible::clone() const { + return std::make_shared(*this); +} + /** * ConditionOutfit */ @@ -2327,6 +2427,9 @@ void ConditionOutfit::serialize(PropWriteStream &propWriteStream) { propWriteStream.write(outfit); } +ConditionOutfit::ConditionOutfit(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + Condition(initId, initType, initTicks, initBuff, initSubId) { } + bool ConditionOutfit::startCondition(std::shared_ptr creature) { if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && outfit.lookType != 0 && !g_game().isLookTypeRegistered(outfit.lookType)) { g_logger().warn("[ConditionOutfit::startCondition] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", outfit.lookType); @@ -2334,7 +2437,7 @@ bool ConditionOutfit::startCondition(std::shared_ptr creature) { } if ((outfit.lookType == 0 && outfit.lookTypeEx == 0) && !monsterName.empty()) { - const auto monsterType = g_monsters().getMonsterType(monsterName); + const auto &monsterType = g_monsters().getMonsterType(monsterName); if (monsterType) { setOutfit(monsterType->info.outfit); } else { @@ -2351,7 +2454,7 @@ bool ConditionOutfit::startCondition(std::shared_ptr creature) { return true; } -bool ConditionOutfit::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionOutfit::executeCondition(const std::shared_ptr &creature, int32_t interval) { return Condition::executeCondition(creature, interval); } @@ -2368,9 +2471,9 @@ void ConditionOutfit::addCondition(std::shared_ptr creature, const std if (updateCondition(addCondition)) { setTicks(addCondition->getTicks()); - const std::shared_ptr &conditionOutfit = addCondition->static_self_cast(); - if (!conditionOutfit->monsterName.empty() && conditionOutfit->monsterName.compare(monsterName) != 0) { - const auto monsterType = g_monsters().getMonsterType(conditionOutfit->monsterName); + const auto &conditionOutfit = addCondition->static_self_cast(); + if (!conditionOutfit->monsterName.empty() && conditionOutfit->monsterName != monsterName) { + const auto &monsterType = g_monsters().getMonsterType(conditionOutfit->monsterName); if (monsterType) { setOutfit(monsterType->info.outfit); } else { @@ -2385,10 +2488,17 @@ void ConditionOutfit::addCondition(std::shared_ptr creature, const std } } +std::shared_ptr ConditionOutfit::clone() const { + return std::make_shared(*this); +} + /** * ConditionLight */ +ConditionLight::ConditionLight(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, uint8_t initLightlevel, uint8_t initLightcolor) : + Condition(initId, initType, initTicks, initBuff, initSubId), lightInfo(initLightlevel, initLightcolor) { } + bool ConditionLight::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; @@ -2401,7 +2511,7 @@ bool ConditionLight::startCondition(std::shared_ptr creature) { return true; } -bool ConditionLight::executeCondition(std::shared_ptr creature, int32_t interval) { +bool ConditionLight::executeCondition(const std::shared_ptr &creature, int32_t interval) { internalLightTicks += interval; if (internalLightTicks >= lightChangeInterval) { @@ -2427,16 +2537,20 @@ void ConditionLight::addCondition(std::shared_ptr creature, const std: if (updateCondition(condition)) { setTicks(condition->getTicks()); - const std::shared_ptr &conditionLight = condition->static_self_cast(); + const auto &conditionLight = condition->static_self_cast(); lightInfo.level = conditionLight->lightInfo.level; lightInfo.color = conditionLight->lightInfo.color; - lightChangeInterval = ticks / lightInfo.level; + lightChangeInterval = ticks / std::max(1, lightInfo.level); internalLightTicks = 0; creature->setCreatureLight(lightInfo); g_game().changeLight(creature); } } +std::shared_ptr ConditionLight::clone() const { + return std::make_shared(*this); +} + bool ConditionLight::setParam(ConditionParam_t param, int32_t value) { bool ret = Condition::setParam(param, value); if (ret) { @@ -2444,9 +2558,13 @@ bool ConditionLight::setParam(ConditionParam_t param, int32_t value) { } switch (param) { - case CONDITION_PARAM_LIGHT_LEVEL: - lightInfo.level = value; + case CONDITION_PARAM_LIGHT_LEVEL: { + if (value < 1) { + g_logger().warn("[ConditionLight::setParam] Trying to set invalid light value: '{}', defaulting to 1.", value); + } + lightInfo.level = std::max(1, static_cast(value)); return true; + } case CONDITION_PARAM_LIGHT_COLOR: lightInfo.color = value; @@ -2510,7 +2628,7 @@ void ConditionSpellCooldown::addCondition(std::shared_ptr creature, co setTicks(addCondition->getTicks()); if (subId != 0 && ticks > 0) { - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendSpellCooldown(subId, ticks); } @@ -2518,13 +2636,20 @@ void ConditionSpellCooldown::addCondition(std::shared_ptr creature, co } } +std::shared_ptr ConditionSpellCooldown::clone() const { + return std::make_shared(*this); +} + +ConditionSpellCooldown::ConditionSpellCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + bool ConditionSpellCooldown::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; } if (subId != 0 && ticks > 0) { - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendSpellCooldown(subId, ticks); } @@ -2541,7 +2666,7 @@ void ConditionSpellGroupCooldown::addCondition(std::shared_ptr creatur setTicks(addCondition->getTicks()); if (subId != 0 && ticks > 0) { - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendSpellGroupCooldown(static_cast(subId), ticks); } @@ -2549,13 +2674,20 @@ void ConditionSpellGroupCooldown::addCondition(std::shared_ptr creatur } } +std::shared_ptr ConditionSpellGroupCooldown::clone() const { + return std::make_shared(*this); +} + +ConditionSpellGroupCooldown::ConditionSpellGroupCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + bool ConditionSpellGroupCooldown::startCondition(std::shared_ptr creature) { if (!Condition::startCondition(creature)) { return false; } if (subId != 0 && ticks > 0) { - std::shared_ptr player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendSpellGroupCooldown(static_cast(subId), ticks); } diff --git a/src/creatures/combat/condition.hpp b/src/creatures/combat/condition.hpp index ea59943e5c7..50d072059a2 100644 --- a/src/creatures/combat/condition.hpp +++ b/src/creatures/combat/condition.hpp @@ -9,9 +9,10 @@ #pragma once -#include "declarations.hpp" +#include "creatures/creatures_definitions.hpp" +#include "game/movement/position.hpp" -#include "enums/player_icons.hpp" +enum class PlayerIcon : uint8_t; class Creature; class Player; @@ -21,34 +22,22 @@ class PropWriteStream; class Condition : public SharedObject { public: Condition() = default; - Condition(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0, bool isPersistent = false) : - endTime(initTicks == -1 ? std::numeric_limits::max() : 0), - subId(initSubId), ticks(initTicks), conditionType(initType), id(initId), isBuff(initBuff), m_isPersistent(isPersistent) { } + Condition(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0, bool isPersistent = false); virtual ~Condition() = default; virtual bool startCondition(std::shared_ptr creature); - virtual bool executeCondition(std::shared_ptr creature, int32_t interval); + virtual bool executeCondition(const std::shared_ptr &creature, int32_t interval); virtual void endCondition(std::shared_ptr creature) = 0; virtual void addCondition(std::shared_ptr creature, std::shared_ptr condition) = 0; virtual std::unordered_set getIcons() const; - ConditionId_t getId() const { - return id; - } - uint32_t getSubId() const { - return subId; - } + ConditionId_t getId() const; + uint32_t getSubId() const; virtual std::shared_ptr clone() const = 0; - ConditionType_t getType() const { - return conditionType; - } - int64_t getEndTime() const { - return endTime; - } - int32_t getTicks() const { - return ticks; - } + ConditionType_t getType() const; + int64_t getEndTime() const; + int32_t getTicks() const; void setTicks(int32_t newTicks); static std::shared_ptr createCondition(ConditionId_t id, ConditionType_t type, int32_t ticks, int32_t param = 0, bool buff = false, uint32_t subId = 0, bool isPersistent = false); @@ -75,7 +64,7 @@ class Condition : public SharedObject { bool isBuff {}; bool m_isPersistent {}; - virtual bool updateCondition(std::shared_ptr addCondition); + virtual bool updateCondition(const std::shared_ptr &addCondition); private: SoundEffect_t tickSound = SoundEffect_t::SILENCE; @@ -87,35 +76,29 @@ class Condition : public SharedObject { class ConditionGeneric : public Condition { public: - ConditionGeneric(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0, bool isPersistent = false) : - Condition(initId, initType, initTicks, initBuff, initSubId, isPersistent) { } + ConditionGeneric(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0, bool isPersistent = false); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; std::unordered_set getIcons() const override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; }; class ConditionAttributes final : public ConditionGeneric { public: - ConditionAttributes(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + ConditionAttributes(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) final; - bool executeCondition(std::shared_ptr creature, int32_t interval) final; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) final; void endCondition(std::shared_ptr creature) final; void addCondition(std::shared_ptr creature, std::shared_ptr condition) final; bool setParam(ConditionParam_t param, int32_t value) final; - std::shared_ptr clone() const final { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; // serialization void serialize(PropWriteStream &propWriteStream) final; @@ -153,39 +136,36 @@ class ConditionAttributes final : public ConditionGeneric { bool disableDefense = false; - void updatePercentStats(std::shared_ptr player); - void updateStats(std::shared_ptr player); - void updatePercentSkills(std::shared_ptr player); - void updateSkills(std::shared_ptr player); - void updateBuffs(std::shared_ptr creature); + void updatePercentStats(const std::shared_ptr &player); + void updateStats(const std::shared_ptr &player) const; + void updatePercentSkills(const std::shared_ptr &player); + void updateSkills(const std::shared_ptr &player) const; + void updateBuffs(const std::shared_ptr &creature) const; // 12.72 mechanics - void updatePercentAbsorbs(std::shared_ptr creature); - void updateAbsorbs(std::shared_ptr creature) const; - void updatePercentIncreases(std::shared_ptr creature); - void updateIncreases(std::shared_ptr creature) const; - void updateCharmChanceModifier(std::shared_ptr creature) const; - void updatePercentBuffs(std::shared_ptr creature); + void updatePercentAbsorbs(const std::shared_ptr &creature); + void updateAbsorbs(const std::shared_ptr &creature) const; + void updatePercentIncreases(const std::shared_ptr &creature); + void updateIncreases(const std::shared_ptr &creature) const; + void updateCharmChanceModifier(const std::shared_ptr &creature) const; + void updatePercentBuffs(const std::shared_ptr &creature); }; class ConditionRegeneration final : public ConditionGeneric { public: - ConditionRegeneration(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, iniTicks, initBuff, initSubId) { } + ConditionRegeneration(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr addCondition) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; bool setParam(ConditionParam_t param, int32_t value) override; - uint32_t getHealthTicks(std::shared_ptr creature) const; - uint32_t getManaTicks(std::shared_ptr creature) const; + uint32_t getHealthTicks(const std::shared_ptr &creature) const; + uint32_t getManaTicks(const std::shared_ptr &creature) const; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; // serialization void serialize(PropWriteStream &propWriteStream) override; @@ -203,8 +183,7 @@ class ConditionRegeneration final : public ConditionGeneric { class ConditionManaShield final : public Condition { public: - ConditionManaShield(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0) : - Condition(initId, initType, iniTicks, initBuff, initSubId) { } + ConditionManaShield(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; void endCondition(std::shared_ptr creature) override; @@ -213,9 +192,7 @@ class ConditionManaShield final : public Condition { bool setParam(ConditionParam_t param, int32_t value) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; // serialization void serialize(PropWriteStream &propWriteStream) override; @@ -227,17 +204,14 @@ class ConditionManaShield final : public Condition { class ConditionSoul final : public ConditionGeneric { public: - ConditionSoul(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, iniTicks, initBuff, initSubId) { } + ConditionSoul(ConditionId_t initId, ConditionType_t initType, int32_t iniTicks, bool initBuff = false, uint32_t initSubId = 0); void addCondition(std::shared_ptr creature, std::shared_ptr addCondition) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; bool setParam(ConditionParam_t param, int32_t value) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; // serialization void serialize(PropWriteStream &propWriteStream) override; @@ -251,41 +225,33 @@ class ConditionSoul final : public ConditionGeneric { class ConditionInvisible final : public ConditionGeneric { public: - ConditionInvisible(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + ConditionInvisible(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; void endCondition(std::shared_ptr creature) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; }; class ConditionDamage final : public Condition { public: ConditionDamage() = default; - ConditionDamage(ConditionId_t intiId, ConditionType_t initType, bool initBuff = false, uint32_t initSubId = 0) : - Condition(intiId, initType, 0, initBuff, initSubId) { } + ConditionDamage(ConditionId_t intiId, ConditionType_t initType, bool initBuff = false, uint32_t initSubId = 0); static void generateDamageList(int32_t amount, int32_t start, std::list &list); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; std::unordered_set getIcons() const override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; bool setParam(ConditionParam_t param, int32_t value) override; bool addDamage(int32_t rounds, int32_t time, int32_t value); - bool doForceUpdate() const { - return forceUpdate; - } + bool doForceUpdate() const; int32_t getTotalDamage() const; // serialization @@ -310,35 +276,32 @@ class ConditionDamage final : public Condition { std::list damageList; bool getNextDamage(int32_t &damage); - bool doDamage(std::shared_ptr creature, int32_t healthChange); + bool doDamage(const std::shared_ptr &creature, int32_t healthChange) const; - bool updateCondition(std::shared_ptr addCondition) override; + bool updateCondition(const std::shared_ptr &addCondition) override; }; class ConditionFeared final : public Condition { public: ConditionFeared() = default; - ConditionFeared(ConditionId_t intiId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : - Condition(intiId, initType, initTicks, initBuff, initSubId) { } + ConditionFeared(ConditionId_t intiId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; std::unordered_set getIcons() const override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; bool setPositionParam(ConditionParam_t param, const Position &pos) override; private: - bool canWalkTo(std::shared_ptr creature, Position pos, Direction moveDirection) const; - bool getFleeDirection(std::shared_ptr creature); - bool getFleePath(std::shared_ptr creature, const Position &pos, std::vector &dirList); - bool getRandomDirection(std::shared_ptr creature, Position pos); - bool isStuck(std::shared_ptr creature, Position pos) const; + bool canWalkTo(const std::shared_ptr &creature, Position pos, Direction moveDirection) const; + bool getFleeDirection(const std::shared_ptr &creature); + bool getFleePath(const std::shared_ptr &creature, const Position &pos, std::vector &dirList); + bool getRandomDirection(const std::shared_ptr &creature, Position pos); + bool isStuck(const std::shared_ptr &creature, Position pos) const; std::vector m_directionsVector { DIRECTION_NORTH, @@ -357,18 +320,15 @@ class ConditionFeared final : public Condition { class ConditionSpeed final : public Condition { public: - ConditionSpeed(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, int32_t initChangeSpeed) : - Condition(initId, initType, initTicks, initBuff, initSubId), speedDelta(initChangeSpeed) { } + ConditionSpeed(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, int32_t initChangeSpeed); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; std::unordered_set getIcons() const override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; bool setParam(ConditionParam_t param, int32_t value) override; @@ -392,17 +352,14 @@ class ConditionSpeed final : public Condition { class ConditionOutfit final : public Condition { public: - ConditionOutfit(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0) : - Condition(initId, initType, initTicks, initBuff, initSubId) { } + ConditionOutfit(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; void setOutfit(const Outfit_t &outfit); void setLazyMonsterOutfit(const std::string &monsterName); @@ -418,17 +375,14 @@ class ConditionOutfit final : public Condition { class ConditionLight final : public Condition { public: - ConditionLight(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, uint8_t initLightlevel, uint8_t initLightcolor) : - Condition(initId, initType, initTicks, initBuff, initSubId), lightInfo(initLightlevel, initLightcolor) { } + ConditionLight(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, uint8_t initLightlevel, uint8_t initLightcolor); bool startCondition(std::shared_ptr creature) override; - bool executeCondition(std::shared_ptr creature, int32_t interval) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; void endCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr addCondition) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; bool setParam(ConditionParam_t param, int32_t value) override; @@ -437,33 +391,27 @@ class ConditionLight final : public Condition { bool unserializeProp(ConditionAttr_t attr, PropStream &propStream) override; private: - LightInfo lightInfo; + LightInfo lightInfo { 1, 215 }; uint32_t internalLightTicks = 0; uint32_t lightChangeInterval = 0; }; class ConditionSpellCooldown final : public ConditionGeneric { public: - ConditionSpellCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + ConditionSpellCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; }; class ConditionSpellGroupCooldown final : public ConditionGeneric { public: - ConditionSpellGroupCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0) : - ConditionGeneric(initId, initType, initTicks, initBuff, initSubId) { } + ConditionSpellGroupCooldown(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff = false, uint32_t initSubId = 0); bool startCondition(std::shared_ptr creature) override; void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; - std::shared_ptr clone() const override { - return std::make_shared(*this); - } + std::shared_ptr clone() const override; }; diff --git a/src/creatures/combat/spells.cpp b/src/creatures/combat/spells.cpp index b7ae69a8bd3..f522eac86a6 100644 --- a/src/creatures/combat/spells.cpp +++ b/src/creatures/combat/spells.cpp @@ -7,24 +7,28 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/combat/combat.hpp" #include "creatures/combat/spells.hpp" -#include "creatures/monsters/monster.hpp" -#include "game/game.hpp" -#include "lua/scripts/lua_environment.hpp" -#include "creatures/players/wheel/player_wheel.hpp" -#include "lua/global/lua_variant.hpp" - -#include "enums/account_type.hpp" +#include "config/configmanager.hpp" +#include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "creatures/players/wheel/wheel_definitions.hpp" #include "enums/account_group_type.hpp" +#include "enums/account_type.hpp" +#include "game/game.hpp" +#include "lua/global/lua_variant.hpp" +#include "lua/scripts/lua_environment.hpp" +#include "lua/scripts/scripts.hpp" +#include "lib/di/container.hpp" Spells::Spells() = default; Spells::~Spells() = default; -TalkActionResult_t Spells::playerSaySpell(std::shared_ptr player, std::string &words) { +TalkActionResult_t Spells::playerSaySpell(const std::shared_ptr &player, std::string &words) { auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT); - auto tile = player->getTile(); + const auto &tile = player->getTile(); if (maxOnline > 1 && player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER && tile && !tile->hasFlag(TILESTATE_PROTECTIONZONE)) { auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT); auto accountPlayers = g_game().getPlayersByAccount(player->getAccount()); @@ -52,7 +56,7 @@ TalkActionResult_t Spells::playerSaySpell(std::shared_ptr player, std::s // strip trailing spaces trimString(str_words); - const std::shared_ptr instantSpell = getInstantSpell(str_words); + const auto &instantSpell = getInstantSpell(str_words); if (!instantSpell) { return TALKACTION_CONTINUE; } @@ -112,7 +116,11 @@ bool Spells::hasInstantSpell(const std::string &word) const { return false; } -bool Spells::registerInstantLuaEvent(const std::shared_ptr instant) { +void Spells::setInstantSpell(const std::string &word, const std::shared_ptr &instant) { + instants.try_emplace(word, instant); +} + +bool Spells::registerInstantLuaEvent(const std::shared_ptr &instant) { if (instant) { // If the spell not have the "spell:words()" return a error message const std::string &instantName = instant->getName(); @@ -131,24 +139,25 @@ bool Spells::registerInstantLuaEvent(const std::shared_ptr instant } // Register spell word in the map setInstantSpell(words, instant); + return true; } return false; } -bool Spells::registerRuneLuaEvent(const std::shared_ptr rune) { +bool Spells::registerRuneLuaEvent(const std::shared_ptr &rune) { if (rune) { uint16_t id = rune->getRuneItemId(); - auto result = runes.emplace(rune->getRuneItemId(), rune); - if (!result.second) { + const auto &[iter, inserted] = runes.try_emplace(rune->getRuneItemId(), rune); + if (!inserted) { g_logger().warn( "[{}] duplicate registered rune with id: {}, for script: {}", __FUNCTION__, id, - rune->getScriptInterface()->getLoadingScriptName() + rune->getRuneSpellScriptInterface()->getLoadingScriptName() ); } - return result.second; + return inserted; } return false; @@ -172,6 +181,14 @@ std::list Spells::getSpellsByVocation(uint16_t vocationId) { return spellsList; } +const std::map> &Spells::getInstantSpells() const { + return instants; +} + +Spells &Spells::getInstance() { + return inject(); +} + std::shared_ptr Spells::getSpellByName(const std::string &name) { std::shared_ptr spell = getRuneSpellByName(name); if (!spell) { @@ -254,45 +271,73 @@ std::shared_ptr Spells::getInstantSpellByName(const std::string &n return nullptr; } -Position Spells::getCasterPosition(std::shared_ptr creature, Direction dir) { +Position Spells::getCasterPosition(const std::shared_ptr &creature, Direction dir) { return getNextPosition(dir, creature->getPosition()); } -CombatSpell::CombatSpell(const std::shared_ptr newCombat, bool newNeedTarget, bool newNeedDirection) : - Script(&g_spells().getScriptInterface()), +LuaScriptInterface* BaseSpell::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool BaseSpell::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_spellScriptId = luaInterface.getEvent(); + if (m_spellScriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t BaseSpell::getScriptId() const { + return m_spellScriptId; +} + +void BaseSpell::setScriptId(int32_t newScriptId) { + m_spellScriptId = newScriptId; +} + +bool BaseSpell::isLoadedScriptId() const { + return m_spellScriptId != 0; +} + +CombatSpell::CombatSpell(const std::shared_ptr &newCombat, bool newNeedTarget, bool newNeedDirection) : m_combat(newCombat), needDirection(newNeedDirection), needTarget(newNeedTarget) { - // Empty } -bool CombatSpell::loadScriptCombat() { - m_combat = g_luaEnvironment().getCombatObject(g_luaEnvironment().lastCombatId); - return m_combat != nullptr; +std::shared_ptr CombatSpell::getCombat() const { + return m_combat; } -bool CombatSpell::castSpell(std::shared_ptr creature) { - if (isLoadedCallback()) { +bool CombatSpell::castSpell(const std::shared_ptr &creature) { + if (isLoadedScriptId()) { LuaVariant var; var.type = VARIANT_POSITION; - if (needDirection) { - var.pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - var.pos = creature->getPosition(); + if (creature) { + if (needDirection) { + var.pos = Spells::getCasterPosition(creature, creature->getDirection()); + } else { + var.pos = creature->getPosition(); + } } return executeCastSpell(creature, var); } Position pos; - if (needDirection) { - pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - pos = creature->getPosition(); + if (creature) { + if (needDirection) { + pos = Spells::getCasterPosition(creature, creature->getDirection()); + } else { + pos = creature->getPosition(); + } } - auto combat = getCombat(); + const auto &combat = getCombat(); if (!combat) { return false; } @@ -309,23 +354,25 @@ bool CombatSpell::castSpell(std::shared_ptr creature) { return true; } -bool CombatSpell::castSpell(std::shared_ptr creature, std::shared_ptr target) { - auto combat = getCombat(); +bool CombatSpell::castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) { + const auto &combat = getCombat(); if (!combat) { return false; } - if (isLoadedCallback()) { + if (isLoadedScriptId()) { LuaVariant var; if (combat->hasArea()) { var.type = VARIANT_POSITION; - if (needTarget) { + if (needTarget && target) { var.pos = target->getPosition(); - } else if (needDirection) { + } else if (needDirection && creature) { var.pos = Spells::getCasterPosition(creature, creature->getDirection()); } else { - var.pos = creature->getPosition(); + if (creature) { + var.pos = creature->getPosition(); + } } } else { var.type = VARIANT_NUMBER; @@ -344,7 +391,7 @@ bool CombatSpell::castSpell(std::shared_ptr creature, std::shared_ptr< } if (combat->hasArea()) { - if (needTarget) { + if (needTarget && target) { combat->doCombat(creature, target->getPosition()); } else { return castSpell(creature); @@ -355,16 +402,16 @@ bool CombatSpell::castSpell(std::shared_ptr creature, std::shared_ptr< return true; } -bool CombatSpell::executeCastSpell(std::shared_ptr creature, const LuaVariant &var) const { +bool CombatSpell::executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var) const { // onCastSpell(creature, var) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaEnvironment::reserveScriptEnv()) { g_logger().error("[CombatSpell::executeCastSpell - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaEnvironment::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -379,7 +426,9 @@ bool CombatSpell::executeCastSpell(std::shared_ptr creature, const Lua return getScriptInterface()->callFunction(2); } -bool Spell::playerSpellCheck(std::shared_ptr player) const { +Spell::Spell() = default; + +bool Spell::playerSpellCheck(const std::shared_ptr &player) const { if (player->hasFlag(PlayerFlags_t::CannotUseSpells)) { return false; } @@ -483,7 +532,7 @@ bool Spell::playerSpellCheck(std::shared_ptr player) const { return true; } -bool Spell::playerInstantSpellCheck(std::shared_ptr player, const Position &toPos) const { +bool Spell::playerInstantSpellCheck(const std::shared_ptr &player, const Position &toPos) const { if (toPos.x == 0xFFFF) { return true; } @@ -499,7 +548,7 @@ bool Spell::playerInstantSpellCheck(std::shared_ptr player, const Positi return false; } - const auto tile = g_game().map.getOrCreateTile(toPos); + const auto &tile = g_game().map.getOrCreateTile(toPos); ReturnValue ret = Combat::canDoCombat(player, tile, aggressive); if (ret != RETURNVALUE_NOERROR) { @@ -523,7 +572,7 @@ bool Spell::playerInstantSpellCheck(std::shared_ptr player, const Positi return true; } -bool Spell::playerRuneSpellCheck(std::shared_ptr player, const Position &toPos) { +bool Spell::playerRuneSpellCheck(const std::shared_ptr &player, const Position &toPos) const { if (!playerSpellCheck(player)) { return false; } @@ -543,7 +592,7 @@ bool Spell::playerRuneSpellCheck(std::shared_ptr player, const Position return false; } - std::shared_ptr tile = g_game().map.getTile(toPos); + const auto &tile = g_game().map.getTile(toPos); if (!tile) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); g_game().addMagicEffect(player->getPosition(), CONST_ME_POFF); @@ -563,12 +612,8 @@ bool Spell::playerRuneSpellCheck(std::shared_ptr player, const Position return false; } - const std::shared_ptr topVisibleCreature = tile->getBottomVisibleCreature(player); - if (blockingCreature && topVisibleCreature) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game().addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } else if (blockingSolid && tile->hasFlag(TILESTATE_BLOCKSOLID) && !topVisibleCreature) { + const auto &topVisibleCreature = tile->getBottomVisibleCreature(player); + if ((blockingCreature && topVisibleCreature) || (blockingSolid && tile->hasFlag(TILESTATE_BLOCKSOLID) && !topVisibleCreature)) { player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); g_game().addMagicEffect(player->getPosition(), CONST_ME_POFF); return false; @@ -581,7 +626,7 @@ bool Spell::playerRuneSpellCheck(std::shared_ptr player, const Position } if (aggressive && needTarget && topVisibleCreature && player->hasSecureMode()) { - const std::shared_ptr targetPlayer = topVisibleCreature->getPlayer(); + const auto &targetPlayer = topVisibleCreature->getPlayer(); if (targetPlayer && targetPlayer != player && player->getSkullClient(targetPlayer) == SKULL_NONE && !Combat::isInPvpZone(player, targetPlayer)) { player->sendCancelMessage(RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS); g_game().addMagicEffect(player->getPosition(), CONST_ME_POFF); @@ -628,16 +673,34 @@ void Spell::setWheelOfDestinyBoost(WheelSpellBoost_t boost, WheelSpellGrade_t gr } } -void Spell::getCombatDataAugment(std::shared_ptr player, CombatDamage &damage) { +const std::string &Spell::getWords() const { + return m_words; +} + +void Spell::setWords(std::string_view newWord) { + m_words = newWord.data(); +} + +const std::string &Spell::getSeparator() const { + return m_separator; +} + +void Spell::setSeparator(std::string_view newSeparator) { + m_separator = newSeparator.data(); +} + +void Spell::getCombatDataAugment(const std::shared_ptr &player, CombatDamage &damage) const { if (!(damage.instantSpellName).empty()) { const auto equippedAugmentItems = player->getEquippedAugmentItems(); for (const auto &item : equippedAugmentItems) { - const auto augments = item->getAugmentsBySpellName(damage.instantSpellName); + const auto &augments = item->getAugmentsBySpellName(damage.instantSpellName); for (auto &augment : augments) { if (augment->value == 0) { continue; } - if (augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact) { + if ( + augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact || augment->type == Augment_t::Base + ) { const float augmentPercent = augment->value / 100.0; damage.primary.value += static_cast(damage.primary.value * augmentPercent); damage.secondary.value += static_cast(damage.secondary.value * augmentPercent); @@ -652,12 +715,12 @@ void Spell::getCombatDataAugment(std::shared_ptr player, CombatDamage &d } }; -int32_t Spell::calculateAugmentSpellCooldownReduction(std::shared_ptr player) const { +int32_t Spell::calculateAugmentSpellCooldownReduction(const std::shared_ptr &player) const { int32_t spellCooldown = 0; - const auto equippedAugmentItems = player->getEquippedAugmentItemsByType(Augment_t::Cooldown); + const auto &equippedAugmentItems = player->getEquippedAugmentItemsByType(Augment_t::Cooldown); for (const auto &item : equippedAugmentItems) { const auto augments = item->getAugmentsBySpellNameAndType(getName(), Augment_t::Cooldown); - for (auto &augment : augments) { + for (const auto &augment : augments) { spellCooldown += augment->value; } } @@ -665,7 +728,7 @@ int32_t Spell::calculateAugmentSpellCooldownReduction(std::shared_ptr pl return spellCooldown; } -void Spell::applyCooldownConditions(std::shared_ptr player) const { +void Spell::applyCooldownConditions(const std::shared_ptr &player) const { WheelSpellGrade_t spellGrade = player->wheel()->getSpellUpgrade(getName()); bool isUpgraded = getWheelOfDestinyUpgraded() && static_cast(spellGrade) > 0; // Safety check to prevent division by zero @@ -683,8 +746,11 @@ void Spell::applyCooldownConditions(std::shared_ptr player) const { g_logger().debug("[{}] spell name: {}, spellCooldown: {}, bonus: {}, augment {}", __FUNCTION__, name, spellCooldown, player->wheel()->getSpellBonus(name, WheelSpellBoost_t::COOLDOWN), augmentCooldownReduction); spellCooldown -= player->wheel()->getSpellBonus(name, WheelSpellBoost_t::COOLDOWN); spellCooldown -= augmentCooldownReduction; + const int32_t halfBaseCooldown = cooldown / 2; + spellCooldown = halfBaseCooldown > spellCooldown ? halfBaseCooldown : spellCooldown; // The cooldown should never be reduced less than half (50%) of its base cooldown if (spellCooldown > 0) { - std::shared_ptr condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, spellCooldown / rateCooldown, 0, false, m_spellId); + player->wheel()->handleTwinBurstsCooldown(player, name, spellCooldown, rateCooldown); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, spellCooldown / rateCooldown, 0, false, m_spellId); player->addCondition(condition); } } @@ -695,7 +761,7 @@ void Spell::applyCooldownConditions(std::shared_ptr player) const { spellGroupCooldown -= getWheelOfDestinyBoost(WheelSpellBoost_t::GROUP_COOLDOWN, spellGrade); } if (spellGroupCooldown > 0) { - std::shared_ptr condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, spellGroupCooldown / rateCooldown, 0, false, group); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, spellGroupCooldown / rateCooldown, 0, false, group); player->addCondition(condition); } } @@ -705,14 +771,32 @@ void Spell::applyCooldownConditions(std::shared_ptr player) const { if (isUpgraded) { spellSecondaryGroupCooldown -= getWheelOfDestinyBoost(WheelSpellBoost_t::SECONDARY_GROUP_COOLDOWN, spellGrade); } + spellSecondaryGroupCooldown -= player->wheel()->getSpellBonus(name, WheelSpellBoost_t::SECONDARY_GROUP_COOLDOWN); if (spellSecondaryGroupCooldown > 0) { - std::shared_ptr condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, spellSecondaryGroupCooldown / rateCooldown, 0, false, secondaryGroup); + player->wheel()->handleBeamMasteryCooldown(player, name, spellSecondaryGroupCooldown, rateCooldown); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, spellSecondaryGroupCooldown / rateCooldown, 0, false, secondaryGroup); player->addCondition(condition); } } } -void Spell::postCastSpell(std::shared_ptr player, bool finishedCast /*= true*/, bool payCost /*= true*/) const { +const std::string &Spell::getName() const { + return name; +} + +void Spell::setName(std::string n) { + name = std::move(n); +} + +uint16_t Spell::getSpellId() const { + return m_spellId; +} + +void Spell::setSpellId(uint16_t id) { + m_spellId = id; +} + +void Spell::postCastSpell(const std::shared_ptr &player, bool finishedCast /*= true*/, bool payCost /*= true*/) const { if (finishedCast) { if (!player->hasFlag(PlayerFlags_t::HasNoExhaustion)) { applyCooldownConditions(player); @@ -729,11 +813,11 @@ void Spell::postCastSpell(std::shared_ptr player, bool finishedCast /*= } if (payCost) { - Spell::postCastSpell(player, getManaCost(player), getSoulCost()); + postCastSpell(player, getManaCost(player), getSoulCost()); } } -void Spell::postCastSpell(std::shared_ptr player, uint32_t manaCost, uint32_t soulCost) { +void Spell::postCastSpell(const std::shared_ptr &player, uint32_t manaCost, uint32_t soulCost) { if (manaCost > 0) { player->addManaSpent(manaCost); player->changeMana(-static_cast(manaCost)); @@ -746,7 +830,11 @@ void Spell::postCastSpell(std::shared_ptr player, uint32_t manaCost, uin } } -uint32_t Spell::getManaCost(std::shared_ptr player) const { +bool Spell::isLearnable() const { + return learnable; +} + +uint32_t Spell::getManaCost(const std::shared_ptr &player) const { WheelSpellGrade_t spellGrade = player->wheel()->getSpellUpgrade(getName()); uint32_t manaRedution = 0; if (getWheelOfDestinyUpgraded() && static_cast(spellGrade) > 0) { @@ -773,7 +861,199 @@ uint32_t Spell::getManaCost(std::shared_ptr player) const { return 0; } -bool InstantSpell::playerCastInstant(std::shared_ptr player, std::string ¶m) { +uint32_t Spell::getSoulCost() const { + return soul; +} + +void Spell::setSoulCost(uint32_t s) { + soul = s; +} + +uint32_t Spell::getLevel() const { + return level; +} + +void Spell::setLevel(uint32_t lvl) { + level = lvl; +} + +uint32_t Spell::getMagicLevel() const { + return magLevel; +} + +void Spell::setMagicLevel(uint32_t lvl) { + magLevel = lvl; +} + +uint32_t Spell::getMana() const { + return mana; +} + +void Spell::setMana(uint32_t m) { + mana = m; +} + +uint32_t Spell::getManaPercent() const { + return manaPercent; +} + +void Spell::setManaPercent(uint32_t m) { + manaPercent = m; +} + +bool Spell::isPremium() const { + return premium; +} + +void Spell::setPremium(bool p) { + premium = p; +} + +bool Spell::isEnabled() const { + return enabled; +} + +void Spell::setEnabled(bool e) { + enabled = e; +} + +const VocSpellMap &Spell::getVocMap() const { + return vocSpellMap; +} + +void Spell::addVocMap(uint16_t vocationId, bool b) { + if (vocationId == 0XFFFF) { + g_logger().error("Vocation overflow for spell: {}", getName()); + return; + } + + g_logger().trace("Adding spell: {} to voc id: {}", getName(), vocationId); + vocSpellMap[vocationId] = b; +} + +SpellGroup_t Spell::getGroup() { + return group; +} + +void Spell::setGroup(SpellGroup_t g) { + group = g; +} + +SpellGroup_t Spell::getSecondaryGroup() { + return secondaryGroup; +} + +void Spell::setSecondaryGroup(SpellGroup_t g) { + secondaryGroup = g; +} + +uint32_t Spell::getCooldown() const { + return cooldown; +} + +void Spell::setCooldown(uint32_t cd) { + cooldown = cd; +} + +uint32_t Spell::getSecondaryCooldown() const { + return secondaryGroupCooldown; +} + +void Spell::setSecondaryCooldown(uint32_t cd) { + secondaryGroupCooldown = cd; +} + +uint32_t Spell::getGroupCooldown() const { + return groupCooldown; +} + +void Spell::setGroupCooldown(uint32_t cd) { + groupCooldown = cd; +} + +int32_t Spell::getRange() const { + return range; +} + +void Spell::setRange(int32_t r) { + range = r; +} + +bool Spell::getNeedTarget() const { + return needTarget; +} + +void Spell::setNeedTarget(bool n) { + needTarget = n; +} + +bool Spell::getNeedWeapon() const { + return needWeapon; +} + +void Spell::setNeedWeapon(bool n) { + needWeapon = n; +} + +bool Spell::getNeedLearn() const { + return learnable; +} + +void Spell::setNeedLearn(bool n) { + learnable = n; +} + +bool Spell::getSelfTarget() const { + return selfTarget; +} + +void Spell::setSelfTarget(bool s) { + selfTarget = s; +} + +bool Spell::getBlockingSolid() const { + return blockingSolid; +} + +void Spell::setBlockingSolid(bool b) { + blockingSolid = b; +} + +bool Spell::getBlockingCreature() const { + return blockingCreature; +} + +void Spell::setBlockingCreature(bool b) { + blockingCreature = b; +} + +bool Spell::getAggressive() const { + return aggressive; +} + +void Spell::setAggressive(bool a) { + aggressive = a; +} + +bool Spell::getAllowOnSelf() const { + return allowOnSelf; +} + +void Spell::setAllowOnSelf(bool s) { + allowOnSelf = s; +} + +bool Spell::getLockedPZ() const { + return pzLocked; +} + +void Spell::setLockedPZ(bool b) { + pzLocked = b; +} + +InstantSpell::InstantSpell() = default; + +bool InstantSpell::playerCastInstant(const std::shared_ptr &player, std::string ¶m) const { if (!playerSpellCheck(player)) { return false; } @@ -895,7 +1175,7 @@ bool InstantSpell::playerCastInstant(std::shared_ptr player, std::string return result; } -bool InstantSpell::canThrowSpell(std::shared_ptr creature, std::shared_ptr target) const { +bool InstantSpell::canThrowSpell(const std::shared_ptr &creature, const std::shared_ptr &target) const { const Position &fromPos = creature->getPosition(); const Position &toPos = target->getPosition(); if (fromPos.z != toPos.z || (range == -1 && !g_game().canThrowObjectTo(fromPos, toPos, checkLineOfSight ? SightLine_CheckSightLineAndFloor : SightLine_NoCheck)) || (range != -1 && !g_game().canThrowObjectTo(fromPos, toPos, checkLineOfSight ? SightLine_CheckSightLineAndFloor : SightLine_NoCheck, range, range))) { @@ -904,12 +1184,12 @@ bool InstantSpell::canThrowSpell(std::shared_ptr creature, std::shared return true; } -bool InstantSpell::castSpell(std::shared_ptr creature) { +bool InstantSpell::castSpell(const std::shared_ptr &creature) { LuaVariant var; var.instantName = getName(); if (casterTargetOrDirection) { - std::shared_ptr target = creature->getAttackedCreature(); + const auto &target = creature->getAttackedCreature(); if (target && target->getHealth() > 0) { if (!canThrowSpell(creature, target)) { return false; @@ -933,27 +1213,26 @@ bool InstantSpell::castSpell(std::shared_ptr creature) { return executeCastSpell(creature, var); } -bool InstantSpell::castSpell(std::shared_ptr creature, std::shared_ptr target) { +bool InstantSpell::castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) { if (needTarget) { LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); return executeCastSpell(creature, var); - } else { - return castSpell(creature); } + return castSpell(creature); } -bool InstantSpell::executeCastSpell(std::shared_ptr creature, const LuaVariant &var) const { +bool InstantSpell::executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var) const { // onCastSpell(creature, var) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaEnvironment::reserveScriptEnv()) { g_logger().error("[InstantSpell::executeCastSpell - Creature {} words {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), getWords()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaEnvironment::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -968,7 +1247,51 @@ bool InstantSpell::executeCastSpell(std::shared_ptr creature, const Lu return getScriptInterface()->callFunction(2); } -bool InstantSpell::canCast(std::shared_ptr player) const { +bool InstantSpell::isInstant() const { + return true; +} + +bool InstantSpell::getHasParam() const { + return hasParam; +} + +void InstantSpell::setHasParam(bool p) { + hasParam = p; +} + +bool InstantSpell::getHasPlayerNameParam() const { + return hasPlayerNameParam; +} + +void InstantSpell::setHasPlayerNameParam(bool p) { + hasPlayerNameParam = p; +} + +bool InstantSpell::getNeedDirection() const { + return needDirection; +} + +void InstantSpell::setNeedDirection(bool n) { + needDirection = n; +} + +bool InstantSpell::getNeedCasterTargetOrDirection() const { + return casterTargetOrDirection; +} + +void InstantSpell::setNeedCasterTargetOrDirection(bool d) { + casterTargetOrDirection = d; +} + +bool InstantSpell::getBlockWalls() const { + return checkLineOfSight; +} + +void InstantSpell::setBlockWalls(bool w) { + checkLineOfSight = w; +} + +bool InstantSpell::canCast(const std::shared_ptr &player) const { if (player->hasFlag(PlayerFlags_t::CannotUseSpells)) { return false; } @@ -990,7 +1313,34 @@ bool InstantSpell::canCast(std::shared_ptr player) const { return false; } -ReturnValue RuneSpell::canExecuteAction(std::shared_ptr player, const Position &toPos) { +LuaScriptInterface* RuneSpell::getRuneSpellScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool RuneSpell::loadRuneSpellScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_runeSpellScriptId = luaInterface.getEvent(); + if (m_runeSpellScriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t RuneSpell::getRuneSpellScriptId() const { + return m_runeSpellScriptId; +} + +void RuneSpell::setRuneSpellScriptId(int32_t newScriptId) { + m_runeSpellScriptId = newScriptId; +} + +bool RuneSpell::isRuneSpellLoadedScriptId() const { + return m_runeSpellScriptId != 0; +} + +ReturnValue RuneSpell::canExecuteAction(const std::shared_ptr &player, const Position &toPos) { if (player->hasFlag(PlayerFlags_t::CannotUseSpells)) { return RETURNVALUE_CANNOTUSETHISOBJECT; } @@ -1011,13 +1361,21 @@ ReturnValue RuneSpell::canExecuteAction(std::shared_ptr player, const Po return RETURNVALUE_NOERROR; } -bool RuneSpell::executeUse(std::shared_ptr player, std::shared_ptr item, const Position &, std::shared_ptr target, const Position &toPosition, bool isHotkey) { +bool RuneSpell::hasOwnErrorHandler() { + return true; +} + +std::shared_ptr RuneSpell::getTarget(const std::shared_ptr &, const std::shared_ptr &targetCreature, const Position &, uint8_t) const { + return targetCreature; +} + +bool RuneSpell::executeUse(const std::shared_ptr &player, const std::shared_ptr &item, const Position &, const std::shared_ptr &target, const Position &toPosition, bool isHotkey) { if (!playerRuneSpellCheck(player, toPosition)) { return false; } // If script not loaded correctly, return - if (!isLoadedCallback()) { + if (!isRuneSpellLoadedScriptId()) { return false; } @@ -1028,9 +1386,9 @@ bool RuneSpell::executeUse(std::shared_ptr player, std::shared_ptr var.type = VARIANT_NUMBER; if (target == nullptr) { - std::shared_ptr toTile = g_game().map.getTile(toPosition); + const auto &toTile = g_game().map.getTile(toPosition); if (toTile) { - std::shared_ptr visibleCreature = toTile->getBottomVisibleCreature(player); + const auto &visibleCreature = toTile->getBottomVisibleCreature(player); if (visibleCreature) { var.number = visibleCreature->getID(); } @@ -1063,7 +1421,7 @@ bool RuneSpell::executeUse(std::shared_ptr player, std::shared_ptr return true; } -bool RuneSpell::castSpell(std::shared_ptr creature) { +bool RuneSpell::castSpell(const std::shared_ptr &creature) { LuaVariant var; var.type = VARIANT_NUMBER; var.number = creature->getID(); @@ -1071,7 +1429,7 @@ bool RuneSpell::castSpell(std::shared_ptr creature) { return internalCastSpell(creature, var, false); } -bool RuneSpell::castSpell(std::shared_ptr creature, std::shared_ptr target) { +bool RuneSpell::castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) { LuaVariant var; var.type = VARIANT_NUMBER; var.number = target->getID(); @@ -1079,31 +1437,31 @@ bool RuneSpell::castSpell(std::shared_ptr creature, std::shared_ptr creature, const LuaVariant &var, bool isHotkey) { +bool RuneSpell::internalCastSpell(const std::shared_ptr &creature, const LuaVariant &var, bool isHotkey) const { bool result; - if (isLoadedCallback()) { - result = executeCastSpell(std::move(creature), var, isHotkey); + if (isRuneSpellLoadedScriptId()) { + result = executeCastSpell(creature, var, isHotkey); } else { result = false; } return result; } -bool RuneSpell::executeCastSpell(std::shared_ptr creature, const LuaVariant &var, bool isHotkey) const { +bool RuneSpell::executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var, bool isHotkey) const { // onCastSpell(creature, var, isHotkey) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaEnvironment::reserveScriptEnv()) { g_logger().error("[RuneSpell::executeCastSpell - Creature {} runeId {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), getRuneItemId()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); - env->setScriptId(getScriptId(), getScriptInterface()); + ScriptEnvironment* env = LuaEnvironment::getScriptEnv(); + env->setScriptId(getRuneSpellScriptId(), getRuneSpellScriptInterface()); - lua_State* L = getScriptInterface()->getLuaState(); + lua_State* L = getRuneSpellScriptInterface()->getLuaState(); - getScriptInterface()->pushFunction(getScriptId()); + getRuneSpellScriptInterface()->pushFunction(getRuneSpellScriptId()); LuaScriptInterface::pushUserdata(L, creature); LuaScriptInterface::setCreatureMetatable(L, -1, creature); @@ -1112,5 +1470,28 @@ bool RuneSpell::executeCastSpell(std::shared_ptr creature, const LuaVa LuaScriptInterface::pushBoolean(L, isHotkey); - return getScriptInterface()->callFunction(3); + return getRuneSpellScriptInterface()->callFunction(3); +} + +bool RuneSpell::isInstant() const { + return false; +} + +uint16_t RuneSpell::getRuneItemId() const { + return runeId; +} + +void RuneSpell::setRuneItemId(uint16_t i) { + runeId = i; +} + +uint32_t RuneSpell::getCharges() const { + return charges; +} + +void RuneSpell::setCharges(uint32_t c) { + if (c > 0) { + hasCharges = true; + } + charges = c; } diff --git a/src/creatures/combat/spells.hpp b/src/creatures/combat/spells.hpp index 5bcc1e02c19..56ff1a330de 100644 --- a/src/creatures/combat/spells.hpp +++ b/src/creatures/combat/spells.hpp @@ -9,22 +9,23 @@ #pragma once -#include "lua/scripts/luascript.hpp" -#include "creatures/players/player.hpp" -#include "creatures/players/wheel/wheel_definitions.hpp" #include "lua/creature/actions.hpp" -#include "lua/creature/talkaction.hpp" -#include "lua/scripts/scripts.hpp" +#include "creatures/players/wheel/wheel_definitions.hpp" class InstantSpell; class RuneSpell; class Spell; +class Combat; +class Player; +class Creature; +class LuaScriptInterface; struct LuaVariant; +struct Position; using VocSpellMap = std::map; -class Spells final : public Scripts { +class Spells { public: Spells(); ~Spells(); @@ -33,9 +34,7 @@ class Spells final : public Scripts { Spells(const Spells &) = delete; Spells &operator=(const Spells &) = delete; - static Spells &getInstance() { - return inject(); - } + static Spells &getInstance(); std::shared_ptr getSpellByName(const std::string &name); std::shared_ptr getRuneSpell(uint16_t id); @@ -46,25 +45,21 @@ class Spells final : public Scripts { std::shared_ptr getInstantSpellById(uint16_t spellId); - TalkActionResult_t playerSaySpell(std::shared_ptr player, std::string &words); + TalkActionResult_t playerSaySpell(const std::shared_ptr &player, std::string &words); - static Position getCasterPosition(std::shared_ptr creature, Direction dir); + static Position getCasterPosition(const std::shared_ptr &creature, Direction dir); std::list getSpellsByVocation(uint16_t vocationId); - [[nodiscard]] const std::map> &getInstantSpells() const { - return instants; - }; + [[nodiscard]] const std::map> &getInstantSpells() const; [[nodiscard]] bool hasInstantSpell(const std::string &word) const; - void setInstantSpell(const std::string &word, const std::shared_ptr instant) { - instants.try_emplace(word, instant); - } + void setInstantSpell(const std::string &word, const std::shared_ptr &instant); void clear(); - bool registerInstantLuaEvent(std::shared_ptr instant); - bool registerRuneLuaEvent(std::shared_ptr rune); + bool registerInstantLuaEvent(const std::shared_ptr &instant); + bool registerRuneLuaEvent(const std::shared_ptr &rune); private: std::map> runes; @@ -75,45 +70,47 @@ class Spells final : public Scripts { constexpr auto g_spells = Spells::getInstance; -using RuneSpellFunction = std::function spell, std::shared_ptr player, const Position &posTo)>; +using RuneSpellFunction [[maybe_unused]] = std::function &spell, const std::shared_ptr &player, const Position &posTo)>; class BaseSpell { public: constexpr BaseSpell() = default; virtual ~BaseSpell() = default; - virtual bool castSpell(std::shared_ptr creature) = 0; - virtual bool castSpell(std::shared_ptr creature, std::shared_ptr target) = 0; + virtual bool castSpell(const std::shared_ptr &creature) = 0; + virtual bool castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) = 0; + + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; SoundEffect_t soundImpactEffect = SoundEffect_t::SILENCE; SoundEffect_t soundCastEffect = SoundEffect_t::SPELL_OR_RUNE; + +protected: + int32_t m_spellScriptId {}; }; -class CombatSpell final : public Script, public BaseSpell, public std::enable_shared_from_this { +class CombatSpell final : public BaseSpell, public std::enable_shared_from_this { public: // Constructor - CombatSpell(std::shared_ptr newCombat, bool newNeedTarget, bool newNeedDirection); + CombatSpell(const std::shared_ptr &newCombat, bool newNeedTarget, bool newNeedDirection); // The copy constructor and the assignment operator have been deleted to prevent accidental copying. CombatSpell(const CombatSpell &) = delete; CombatSpell &operator=(const CombatSpell &) = delete; - bool castSpell(std::shared_ptr creature) override; - bool castSpell(std::shared_ptr creature, std::shared_ptr target) override; + bool castSpell(const std::shared_ptr &creature) override; + bool castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) override; // Scripting spell - bool executeCastSpell(std::shared_ptr creature, const LuaVariant &var) const; + bool executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var) const; - bool loadScriptCombat(); - std::shared_ptr getCombat() const { - return m_combat; - } + std::shared_ptr getCombat() const; private: - std::string getScriptTypeName() const override { - return "onCastSpell"; - } - std::shared_ptr m_combat; bool needDirection; @@ -122,178 +119,70 @@ class CombatSpell final : public Script, public BaseSpell, public std::enable_sh class Spell : public BaseSpell { public: - Spell() = default; - - [[nodiscard]] const std::string &getName() const { - return name; - } - void setName(std::string n) { - name = std::move(n); - } - [[nodiscard]] uint16_t getSpellId() const { - return m_spellId; - } - void setSpellId(uint16_t id) { - m_spellId = id; - } - - void postCastSpell(std::shared_ptr player, bool finishedCast = true, bool payCost = true) const; - static void postCastSpell(std::shared_ptr player, uint32_t manaCost, uint32_t soulCost); + Spell(); + + [[nodiscard]] const std::string &getName() const; + void setName(std::string n); + [[nodiscard]] uint16_t getSpellId() const; + void setSpellId(uint16_t id); + + void postCastSpell(const std::shared_ptr &player, bool finishedCast = true, bool payCost = true) const; + static void postCastSpell(const std::shared_ptr &player, uint32_t manaCost, uint32_t soulCost); [[nodiscard]] virtual bool isInstant() const = 0; - [[nodiscard]] bool isLearnable() const { - return learnable; - } - - uint32_t getManaCost(std::shared_ptr player) const; - [[nodiscard]] uint32_t getSoulCost() const { - return soul; - } - void setSoulCost(uint32_t s) { - soul = s; - } - [[nodiscard]] uint32_t getLevel() const { - return level; - } - void setLevel(uint32_t lvl) { - level = lvl; - } - [[nodiscard]] uint32_t getMagicLevel() const { - return magLevel; - } - void setMagicLevel(uint32_t lvl) { - magLevel = lvl; - } - [[nodiscard]] uint32_t getMana() const { - return mana; - } - void setMana(uint32_t m) { - mana = m; - } - [[nodiscard]] uint32_t getManaPercent() const { - return manaPercent; - } - void setManaPercent(uint32_t m) { - manaPercent = m; - } - [[nodiscard]] bool isPremium() const { - return premium; - } - void setPremium(bool p) { - premium = p; - } - [[nodiscard]] bool isEnabled() const { - return enabled; - } - void setEnabled(bool e) { - enabled = e; - } - - [[nodiscard]] const VocSpellMap &getVocMap() const { - return vocSpellMap; - } - void addVocMap(uint16_t vocationId, bool b) { - if (vocationId == 0XFFFF) { - g_logger().error("Vocation overflow for spell: {}", getName()); - return; - } - - g_logger().trace("Adding spell: {} to voc id: {}", getName(), vocationId); - vocSpellMap[vocationId] = b; - } - - SpellGroup_t getGroup() { - return group; - } - void setGroup(SpellGroup_t g) { - group = g; - } - SpellGroup_t getSecondaryGroup() { - return secondaryGroup; - } - void setSecondaryGroup(SpellGroup_t g) { - secondaryGroup = g; - } - - [[nodiscard]] uint32_t getCooldown() const { - return cooldown; - } - void setCooldown(uint32_t cd) { - cooldown = cd; - } - [[nodiscard]] uint32_t getSecondaryCooldown() const { - return secondaryGroupCooldown; - } - void setSecondaryCooldown(uint32_t cd) { - secondaryGroupCooldown = cd; - } - [[nodiscard]] uint32_t getGroupCooldown() const { - return groupCooldown; - } - void setGroupCooldown(uint32_t cd) { - groupCooldown = cd; - } - - [[nodiscard]] int32_t getRange() const { - return range; - } - void setRange(int32_t r) { - range = r; - } - - [[nodiscard]] bool getNeedTarget() const { - return needTarget; - } - void setNeedTarget(bool n) { - needTarget = n; - } - [[nodiscard]] bool getNeedWeapon() const { - return needWeapon; - } - void setNeedWeapon(bool n) { - needWeapon = n; - } - [[nodiscard]] bool getNeedLearn() const { - return learnable; - } - void setNeedLearn(bool n) { - learnable = n; - } - [[nodiscard]] bool getSelfTarget() const { - return selfTarget; - } - void setSelfTarget(bool s) { - selfTarget = s; - } - [[nodiscard]] bool getBlockingSolid() const { - return blockingSolid; - } - void setBlockingSolid(bool b) { - blockingSolid = b; - } - [[nodiscard]] bool getBlockingCreature() const { - return blockingCreature; - } - void setBlockingCreature(bool b) { - blockingCreature = b; - } - [[nodiscard]] bool getAggressive() const { - return aggressive; - } - void setAggressive(bool a) { - aggressive = a; - } - [[nodiscard]] bool getAllowOnSelf() const { - return allowOnSelf; - } - void setAllowOnSelf(bool s) { - allowOnSelf = s; - } - [[nodiscard]] bool getLockedPZ() const { - return pzLocked; - } - void setLockedPZ(bool b) { - pzLocked = b; - } + [[nodiscard]] bool isLearnable() const; + + uint32_t getManaCost(const std::shared_ptr &player) const; + [[nodiscard]] uint32_t getSoulCost() const; + void setSoulCost(uint32_t s); + [[nodiscard]] uint32_t getLevel() const; + void setLevel(uint32_t lvl); + [[nodiscard]] uint32_t getMagicLevel() const; + void setMagicLevel(uint32_t lvl); + [[nodiscard]] uint32_t getMana() const; + void setMana(uint32_t m); + [[nodiscard]] uint32_t getManaPercent() const; + void setManaPercent(uint32_t m); + [[nodiscard]] bool isPremium() const; + void setPremium(bool p); + [[nodiscard]] bool isEnabled() const; + void setEnabled(bool e); + + [[nodiscard]] const VocSpellMap &getVocMap() const; + void addVocMap(uint16_t vocationId, bool b); + + SpellGroup_t getGroup(); + void setGroup(SpellGroup_t g); + SpellGroup_t getSecondaryGroup(); + void setSecondaryGroup(SpellGroup_t g); + + [[nodiscard]] uint32_t getCooldown() const; + void setCooldown(uint32_t cd); + [[nodiscard]] uint32_t getSecondaryCooldown() const; + void setSecondaryCooldown(uint32_t cd); + [[nodiscard]] uint32_t getGroupCooldown() const; + void setGroupCooldown(uint32_t cd); + + [[nodiscard]] int32_t getRange() const; + void setRange(int32_t r); + + [[nodiscard]] bool getNeedTarget() const; + void setNeedTarget(bool n); + [[nodiscard]] bool getNeedWeapon() const; + void setNeedWeapon(bool n); + [[nodiscard]] bool getNeedLearn() const; + void setNeedLearn(bool n); + [[nodiscard]] bool getSelfTarget() const; + void setSelfTarget(bool s); + [[nodiscard]] bool getBlockingSolid() const; + void setBlockingSolid(bool b); + [[nodiscard]] bool getBlockingCreature() const; + void setBlockingCreature(bool b); + [[nodiscard]] bool getAggressive() const; + void setAggressive(bool a); + [[nodiscard]] bool getAllowOnSelf() const; + void setAllowOnSelf(bool s); + [[nodiscard]] bool getLockedPZ() const; + void setLockedPZ(bool b); /** * @brief Get whether the wheel of destiny is upgraded. @@ -327,37 +216,28 @@ class Spell : public BaseSpell { */ void setWheelOfDestinyBoost(WheelSpellBoost_t boost, WheelSpellGrade_t grade, int32_t value); - SpellType_t spellType = SPELL_UNDEFINED; - - [[nodiscard]] const std::string &getWords() const { - return m_words; - } + [[nodiscard]] const std::string &getWords() const; - void setWords(std::string_view newWord) { - m_words = newWord.data(); - } + void setWords(std::string_view newWord); - [[nodiscard]] const std::string &getSeparator() const { - return m_separator; - } + [[nodiscard]] const std::string &getSeparator() const; - void setSeparator(std::string_view newSeparator) { - m_separator = newSeparator.data(); - } + void setSeparator(std::string_view newSeparator); - void getCombatDataAugment(std::shared_ptr player, CombatDamage &damage); - int32_t calculateAugmentSpellCooldownReduction(std::shared_ptr player) const; + void getCombatDataAugment(const std::shared_ptr &player, CombatDamage &damage) const; + int32_t calculateAugmentSpellCooldownReduction(const std::shared_ptr &player) const; protected: - void applyCooldownConditions(std::shared_ptr player) const; - bool playerSpellCheck(std::shared_ptr player) const; - bool playerInstantSpellCheck(std::shared_ptr player, const Position &toPos) const; - bool playerRuneSpellCheck(std::shared_ptr player, const Position &toPos); + void applyCooldownConditions(const std::shared_ptr &player) const; + bool playerSpellCheck(const std::shared_ptr &player) const; + bool playerInstantSpellCheck(const std::shared_ptr &player, const Position &toPos) const; + bool playerRuneSpellCheck(const std::shared_ptr &player, const Position &toPos) const; VocSpellMap vocSpellMap; SpellGroup_t group = SPELLGROUP_NONE; SpellGroup_t secondaryGroup = SPELLGROUP_NONE; + SpellType_t spellType = SPELL_UNDEFINED; uint32_t cooldown = 1000; uint32_t groupCooldown = 1000; @@ -393,61 +273,36 @@ class Spell : public BaseSpell { std::string name; std::string m_words; std::string m_separator; + + friend class SpellFunctions; }; -class InstantSpell final : public Script, public Spell { +class InstantSpell final : public Spell { public: - using Script::Script; + InstantSpell(); + bool playerCastInstant(const std::shared_ptr &player, std::string ¶m) const; - virtual bool playerCastInstant(std::shared_ptr player, std::string ¶m); - - bool castSpell(std::shared_ptr creature) override; - bool castSpell(std::shared_ptr creature, std::shared_ptr target) override; + bool castSpell(const std::shared_ptr &creature) override; + bool castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) override; // Scripting spell - bool executeCastSpell(std::shared_ptr creature, const LuaVariant &var) const; - - [[nodiscard]] bool isInstant() const override { - return true; - } - [[nodiscard]] bool getHasParam() const { - return hasParam; - } - void setHasParam(bool p) { - hasParam = p; - } - [[nodiscard]] bool getHasPlayerNameParam() const { - return hasPlayerNameParam; - } - void setHasPlayerNameParam(bool p) { - hasPlayerNameParam = p; - } - [[nodiscard]] bool getNeedDirection() const { - return needDirection; - } - void setNeedDirection(bool n) { - needDirection = n; - } - [[nodiscard]] bool getNeedCasterTargetOrDirection() const { - return casterTargetOrDirection; - } - void setNeedCasterTargetOrDirection(bool d) { - casterTargetOrDirection = d; - } - [[nodiscard]] bool getBlockWalls() const { - return checkLineOfSight; - } - void setBlockWalls(bool w) { - checkLineOfSight = w; - } - bool canCast(std::shared_ptr player) const; - bool canThrowSpell(std::shared_ptr creature, std::shared_ptr target) const; + bool executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var) const; + + [[nodiscard]] bool isInstant() const override; + [[nodiscard]] bool getHasParam() const; + void setHasParam(bool p); + [[nodiscard]] bool getHasPlayerNameParam() const; + void setHasPlayerNameParam(bool p); + [[nodiscard]] bool getNeedDirection() const; + void setNeedDirection(bool n); + [[nodiscard]] bool getNeedCasterTargetOrDirection() const; + void setNeedCasterTargetOrDirection(bool d); + [[nodiscard]] bool getBlockWalls() const; + void setBlockWalls(bool w); + bool canCast(const std::shared_ptr &player) const; + bool canThrowSpell(const std::shared_ptr &creature, const std::shared_ptr &target) const; private: - [[nodiscard]] std::string getScriptTypeName() const override { - return "onCastSpell"; - } - bool needDirection = false; bool hasParam = false; bool hasPlayerNameParam = false; @@ -459,47 +314,34 @@ class RuneSpell final : public Action, public Spell { public: using Action::Action; - ReturnValue canExecuteAction(std::shared_ptr player, const Position &toPos) override; - bool hasOwnErrorHandler() override { - return true; - } - std::shared_ptr getTarget(std::shared_ptr, std::shared_ptr targetCreature, const Position &, uint8_t) const override { - return targetCreature; - } + LuaScriptInterface* getRuneSpellScriptInterface() const; + bool loadRuneSpellScriptId(); + int32_t getRuneSpellScriptId() const; + void setRuneSpellScriptId(int32_t newScriptId); + bool isRuneSpellLoadedScriptId() const; - bool executeUse(std::shared_ptr player, std::shared_ptr item, const Position &fromPosition, std::shared_ptr target, const Position &toPosition, bool isHotkey) override; + ReturnValue canExecuteAction(const std::shared_ptr &player, const Position &toPos) override; + bool hasOwnErrorHandler() override; + std::shared_ptr getTarget(const std::shared_ptr &, const std::shared_ptr &targetCreature, const Position &, uint8_t) const override; - bool castSpell(std::shared_ptr creature) override; - bool castSpell(std::shared_ptr creature, std::shared_ptr target) override; + bool executeUse(const std::shared_ptr &player, const std::shared_ptr &item, const Position &fromPosition, const std::shared_ptr &target, const Position &toPosition, bool isHotkey) override; + + bool castSpell(const std::shared_ptr &creature) override; + bool castSpell(const std::shared_ptr &creature, const std::shared_ptr &target) override; // Scripting spell - bool executeCastSpell(std::shared_ptr creature, const LuaVariant &var, bool isHotkey) const; - - [[nodiscard]] bool isInstant() const override { - return false; - } - [[nodiscard]] uint16_t getRuneItemId() const { - return runeId; - } - void setRuneItemId(uint16_t i) { - runeId = i; - } - [[nodiscard]] uint32_t getCharges() const { - return charges; - } - void setCharges(uint32_t c) { - if (c > 0) { - hasCharges = true; - } - charges = c; - } + bool executeCastSpell(const std::shared_ptr &creature, const LuaVariant &var, bool isHotkey) const; + + [[nodiscard]] bool isInstant() const override; + [[nodiscard]] uint16_t getRuneItemId() const; + void setRuneItemId(uint16_t i); + [[nodiscard]] uint32_t getCharges() const; + void setCharges(uint32_t c); private: - [[nodiscard]] std::string getScriptTypeName() const override { - return "onCastSpell"; - } + bool internalCastSpell(const std::shared_ptr &creature, const LuaVariant &var, bool isHotkey) const; - bool internalCastSpell(std::shared_ptr creature, const LuaVariant &var, bool isHotkey); + int32_t m_runeSpellScriptId = 0; uint16_t runeId = 0; uint32_t charges = 0; diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp index 17c99a00d38..32f3c598b81 100644 --- a/src/creatures/creature.cpp +++ b/src/creatures/creature.cpp @@ -8,16 +8,23 @@ */ #include "creatures/creature.hpp" -#include "declarations.hpp" -#include "game/scheduling/dispatcher.hpp" -#include "game/game.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/combat/combat.hpp" #include "creatures/monsters/monster.hpp" +#include "creatures/players/grouping/party.hpp" +#include "game/game.hpp" +#include "game/scheduling/dispatcher.hpp" #include "game/zones/zone.hpp" -#include "map/spectators.hpp" #include "lib/metrics/metrics.hpp" +#include "lua/creature/creatureevent.hpp" +#include "map/spectators.hpp" +#include "creatures/players/player.hpp" +#include "server/network/protocol/protocolgame.hpp" Creature::Creature() { - onIdleStatus(); + Creature::onIdleStatus(); } Creature::~Creature() { @@ -28,7 +35,7 @@ Creature::~Creature() { } bool Creature::canSee(const Position &myPos, const Position &pos, int32_t viewRangeX, int32_t viewRangeY) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (myPos.z <= MAP_INIT_SURFACE_LAYER) { // we are on ground level or above (7 -> 0) // view is from 7 -> 0 @@ -52,7 +59,7 @@ bool Creature::canSee(const Position &pos) { return canSee(getPosition(), pos, MAP_MAX_VIEW_PORT_X, MAP_MAX_VIEW_PORT_Y); } -bool Creature::canSeeCreature(std::shared_ptr creature) const { +bool Creature::canSeeCreature(const std::shared_ptr &creature) const { if (!canSeeInvisibility() && creature->isInvisible()) { return false; } @@ -88,19 +95,15 @@ int32_t Creature::getWalkSize() { } void Creature::onThink(uint32_t interval) { - metrics::method_latency measure(__METHOD_NAME__); - if (!isMapLoaded && useCacheMap()) { - isMapLoaded = true; - updateMapCache(); - } + metrics::method_latency measure(__METRICS_METHOD_NAME__); - auto followCreature = getFollowCreature(); - auto master = getMaster(); + const auto &followCreature = getFollowCreature(); + const auto &master = getMaster(); if (followCreature && master != followCreature && !canSeeCreature(followCreature)) { onCreatureDisappear(followCreature, false); } - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature)) { onCreatureDisappear(attackedCreature, false); } @@ -138,7 +141,7 @@ void Creature::onThink(uint32_t interval) { } void Creature::onAttacking(uint32_t interval) { - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (!attackedCreature) { return; } @@ -165,7 +168,7 @@ void Creature::onCreatureWalk() { checkingWalkCreature = true; - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); g_dispatcher().addWalkEvent([self = getCreature(), this] { checkingWalkCreature = false; @@ -263,18 +266,17 @@ void Creature::addEventWalk(bool firstStep) { return; } - g_dispatcher().context().tryAddEvent([ticks, self = getCreature()]() { + safeCall([this, ticks]() { // Take first step right away, but still queue the next if (ticks == 1) { - g_game().checkCreatureWalk(self->getID()); + g_game().checkCreatureWalk(getID()); } - self->eventWalk = g_dispatcher().scheduleEvent( + eventWalk = g_dispatcher().scheduleEvent( static_cast(ticks), - [creatureId = self->getID()] { g_game().checkCreatureWalk(creatureId); }, "Game::checkCreatureWalk" + [creatureId = getID()] { g_game().checkCreatureWalk(creatureId); }, "Game::checkCreatureWalk" ); - }, - "addEventWalk"); + }); } void Creature::stopEventWalk() { @@ -284,135 +286,28 @@ void Creature::stopEventWalk() { } } -void Creature::updateMapCache() { - if (!useCacheMap()) { - return; - } - - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr newTile; - const Position &myPos = getPosition(); - Position pos(0, 0, myPos.z); - - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - pos.x = myPos.getX() + x; - pos.y = myPos.getY() + y; - newTile = g_game().map.getTile(pos); - updateTileCache(newTile, pos); - } - } -} - -void Creature::updateTileCache(std::shared_ptr newTile, int32_t dx, int32_t dy) { - metrics::method_latency measure(__METHOD_NAME__); - if (std::abs(dx) <= maxWalkCacheWidth && std::abs(dy) <= maxWalkCacheHeight) { - localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx] = newTile && newTile->queryAdd(0, getCreature(), 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RETURNVALUE_NOERROR; - } -} - -void Creature::updateTileCache(std::shared_ptr upTile, const Position &pos) { - const Position &myPos = getPosition(); - if (pos.z == myPos.z) { - int32_t dx = Position::getOffsetX(pos, myPos); - int32_t dy = Position::getOffsetY(pos, myPos); - updateTileCache(std::move(upTile), dx, dy); - } -} - -int32_t Creature::getWalkCache(const Position &pos) { - metrics::method_latency measure(__METHOD_NAME__); - if (!useCacheMap()) { - return 2; - } - - const Position &myPos = getPosition(); - if (myPos.z != pos.z) { - return 0; - } - - if (pos == myPos) { - return 1; - } - - int32_t dx = Position::getOffsetX(pos, myPos); - if (std::abs(dx) <= maxWalkCacheWidth) { - int32_t dy = Position::getOffsetY(pos, myPos); - if (std::abs(dy) <= maxWalkCacheHeight) { - return localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]; - } - } - - // out of range - return 2; -} - -void Creature::onAddTileItem(std::shared_ptr tileItem, const Position &pos) { - if (isMapLoaded && pos.z == getPosition().z) { - updateTileCache(std::move(tileItem), pos); - } -} - -void Creature::onUpdateTileItem(std::shared_ptr updateTile, const Position &pos, std::shared_ptr, const ItemType &oldType, std::shared_ptr, const ItemType &newType) { - if (!isMapLoaded) { - return; - } - - if (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind || newType.blockSolid) { - if (pos.z == getPosition().z) { - updateTileCache(std::move(updateTile), pos); - } - } -} - -void Creature::onRemoveTileItem(std::shared_ptr updateTile, const Position &pos, const ItemType &iType, std::shared_ptr) { - if (!isMapLoaded) { - return; - } - - if (iType.blockSolid || iType.blockPathFind || iType.isGroundTile()) { - if (pos.z == getPosition().z) { - updateTileCache(std::move(updateTile), pos); - } - } -} - -void Creature::onCreatureAppear(std::shared_ptr creature, bool isLogin) { - metrics::method_latency measure(__METHOD_NAME__); +void Creature::onCreatureAppear(const std::shared_ptr &creature, bool isLogin) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (creature.get() == this) { - if (useCacheMap()) { - isMapLoaded = true; - updateMapCache(); - } - if (isLogin) { setLastPosition(getPosition()); } - } else if (isMapLoaded) { - if (creature->getPosition().z == getPosition().z) { - updateTileCache(creature->getTile(), creature->getPosition()); - } } } -void Creature::onRemoveCreature(std::shared_ptr creature, bool) { - metrics::method_latency measure(__METHOD_NAME__); +void Creature::onRemoveCreature(const std::shared_ptr &creature, bool) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); onCreatureDisappear(creature, true); - if (creature != getCreature() && isMapLoaded) { - if (creature->getPosition().z == getPosition().z) { - updateTileCache(creature->getTile(), creature->getPosition()); - } - } // Update player from monster target list (avoid memory usage after clean) - if (auto monster = getMonster(); monster && monster->getAttackedCreature() == creature) { + if (const auto &monster = getMonster(); monster && monster->getAttackedCreature() == creature) { monster->setAttackedCreature(creature); monster->setFollowCreature(creature); } } -void Creature::onCreatureDisappear(std::shared_ptr creature, bool isLogout) { - metrics::method_latency measure(__METHOD_NAME__); +void Creature::onCreatureDisappear(const std::shared_ptr &creature, bool isLogout) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (getAttackedCreature() == creature) { setAttackedCreature(nullptr); onAttackedCreatureDisappear(isLogout); @@ -425,17 +320,17 @@ void Creature::onCreatureDisappear(std::shared_ptr creature, bool isLo } void Creature::onChangeZone(ZoneType_t zone) { - metrics::method_latency measure(__METHOD_NAME__); - auto attackedCreature = getAttackedCreature(); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &attackedCreature = getAttackedCreature(); if (attackedCreature && zone == ZONE_PROTECTION) { onCreatureDisappear(attackedCreature, false); } } void Creature::onAttackedCreatureChangeZone(ZoneType_t zone) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (zone == ZONE_PROTECTION) { - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (attackedCreature) { onCreatureDisappear(attackedCreature, false); } @@ -443,10 +338,14 @@ void Creature::onAttackedCreatureChangeZone(ZoneType_t zone) { } void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (hasSummons()) { std::vector> despawnMonsterList; for (const auto &summon : getSummons()) { + if (!summon) { + continue; + } + const auto &pos = summon->getPosition(); const auto &monster = summon->getMonster(); const auto &tile = getTile(); @@ -486,7 +385,7 @@ void Creature::checkSummonMove(const Position &newPos, bool teleportSummon) { } void Creature::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (creature.get() == this) { lastStep = OTSYS_TIME(); lastStepCost = 1; @@ -507,7 +406,7 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s handleLostSummon(configTeleportSummons); } - if (std::shared_ptr player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { if (player->isExerciseTraining()) { player->setTraining(false); } @@ -516,101 +415,6 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s if (newTile->getZoneType() != oldTile->getZoneType()) { onChangeZone(getZoneType()); } - - // update map cache - if (isMapLoaded) { - if (teleport || oldPos.z != newPos.z) { - updateMapCache(); - } else { - const Position &myPos = getPosition(); - - if (oldPos.y > newPos.y) { // north - // shift y south - for (int32_t y = mapWalkHeight - 1; --y >= 0;) { - std::ranges::copy(std::span(localMapCache[y]), localMapCache[y + 1]); - } - - // update 0 - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - const auto &cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() - maxWalkCacheHeight), myPos.z); - updateTileCache(cacheTile, x, -maxWalkCacheHeight); - } - } else if (oldPos.y < newPos.y) { // south - // shift y north - for (int32_t y = 0; y <= mapWalkHeight - 2; ++y) { - std::ranges::copy(std::span(localMapCache[y + 1]), localMapCache[y]); - } - - // update mapWalkHeight - 1 - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - const auto &cacheTile = g_game().map.getTile(static_cast(myPos.getX() + x), static_cast(myPos.getY() + maxWalkCacheHeight), myPos.z); - updateTileCache(cacheTile, x, maxWalkCacheHeight); - } - } - - if (oldPos.x < newPos.x) { // east - // shift y west - int32_t starty = 0; - int32_t endy = mapWalkHeight - 1; - int32_t dy = Position::getDistanceY(oldPos, newPos); - - if (dy < 0) { - endy += dy; - } else if (dy > 0) { - starty = dy; - } - - for (int32_t y = starty; y <= endy; ++y) { - for (int32_t x = 0; x <= mapWalkWidth - 2; ++x) { - localMapCache[y][x] = localMapCache[y][x + 1]; - } - } - - // update mapWalkWidth - 1 - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - const auto &cacheTile = g_game().map.getTile(myPos.x + maxWalkCacheWidth, static_cast(myPos.y + y), myPos.z); - updateTileCache(cacheTile, maxWalkCacheWidth, y); - } - } else if (oldPos.x > newPos.x) { // west - // shift y east - int32_t starty = 0; - int32_t endy = mapWalkHeight - 1; - int32_t dy = Position::getDistanceY(oldPos, newPos); - - if (dy < 0) { - endy += dy; - } else if (dy > 0) { - starty = dy; - } - - for (int32_t y = starty; y <= endy; ++y) { - for (int32_t x = mapWalkWidth - 1; --x >= 0;) { - localMapCache[y][x + 1] = localMapCache[y][x]; - } - } - - // update 0 - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - std::shared_ptr cacheTile = g_game().map.getTile(myPos.x - maxWalkCacheWidth, static_cast(myPos.y + y), myPos.z); - updateTileCache(cacheTile, -maxWalkCacheWidth, y); - } - } - - updateTileCache(oldTile, oldPos); - } - } - } else { - if (isMapLoaded) { - const Position &myPos = getPosition(); - - if (newPos.z == myPos.z) { - updateTileCache(newTile, newPos); - } - - if (oldPos.z == myPos.z) { - updateTileCache(oldTile, oldPos); - } - } } const auto &followCreature = getFollowCreature(); @@ -643,10 +447,10 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s } void Creature::onDeath() { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); bool lastHitUnjustified = false; bool mostDamageUnjustified = false; - std::shared_ptr lastHitCreature = g_game().getCreatureByID(lastHitCreatureId); + const auto &lastHitCreature = g_game().getCreatureByID(lastHitCreatureId); std::shared_ptr lastHitCreatureMaster; if (lastHitCreature && getPlayer()) { /** @@ -666,21 +470,29 @@ void Creature::onDeath() { int32_t mostDamage = 0; std::map, uint64_t> experienceMap; std::unordered_set> killers; - for (const auto &it : damageMap) { - if (auto attacker = g_game().getCreatureByID(it.first)) { - CountBlock_t cb = it.second; - if ((cb.total > mostDamage && (timeNow - cb.ticks <= inFightTicks))) { - mostDamage = cb.total; + for (const auto &[creatureId, damageInfo] : damageMap) { + if (creatureId == 0) { + continue; + } + + if (auto attacker = g_game().getCreatureByID(creatureId)) { + const auto &[total, ticks] = damageInfo; + if (total == 0 || ticks == 0) { + continue; + } + + if (total > mostDamage && timeNow - ticks <= inFightTicks) { + mostDamage = total; mostDamageCreature = attacker; } if (attacker != getCreature()) { - uint64_t gainExp = getGainedExperience(attacker); - auto attackerMaster = attacker->getMaster() ? attacker->getMaster() : attacker; + const uint64_t gainExp = getGainedExperience(attacker); + const auto &attackerMaster = attacker->getMaster() ? attacker->getMaster() : attacker; if (auto attackerPlayer = attackerMaster->getPlayer()) { attackerPlayer->removeAttacked(getPlayer()); - auto party = attackerPlayer->getParty(); + const auto &party = attackerPlayer->getParty(); killers.insert(attackerPlayer); if (party && party->getLeader() && party->isSharedExperienceActive() && party->isSharedExperienceEnabled()) { attacker = party->getLeader(); @@ -703,15 +515,15 @@ void Creature::onDeath() { } } - for (const auto &it : experienceMap) { - it.first->onGainExperience(it.second, getCreature()); + for (const auto &[creature, experience] : experienceMap) { + creature->onGainExperience(experience, getCreature()); } mostDamageCreature = mostDamageCreature && mostDamageCreature->getMaster() ? mostDamageCreature->getMaster() : mostDamageCreature; for (const auto &killer : killers) { - if (auto monster = getMonster()) { + if (const auto &monster = getMonster()) { killer->onKilledMonster(monster); - } else if (auto player = getPlayer(); player && mostDamageCreature != killer) { + } else if (const auto &player = getPlayer(); player && mostDamageCreature != killer) { killer->onKilledPlayer(player, false); } } @@ -719,7 +531,7 @@ void Creature::onDeath() { /** * @deprecated -- This is here to trigger the deprecated onKill events in lua */ - auto mostDamageCreatureMaster = mostDamageCreature ? mostDamageCreature->getMaster() : nullptr; + const auto &mostDamageCreatureMaster = mostDamageCreature ? mostDamageCreature->getMaster() : nullptr; if (mostDamageCreature && (mostDamageCreature != lastHitCreature || getMonster()) && mostDamageCreature != lastHitCreatureMaster) { if (lastHitCreature != mostDamageCreatureMaster && (lastHitCreatureMaster == nullptr || mostDamageCreatureMaster != lastHitCreatureMaster)) { mostDamageUnjustified = mostDamageCreature->deprecatedOnKilledCreature(getCreature(), false); @@ -772,8 +584,8 @@ void Creature::onDeath() { } } -bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) { - metrics::method_latency measure(__METHOD_NAME__); +bool Creature::dropCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (!lootDrop && getMonster()) { if (getMaster()) { // Scripting event onDeath @@ -804,22 +616,22 @@ bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared break; } - std::shared_ptr tile = getTile(); + const auto &tile = getTile(); if (tile && splash) { g_game().internalAddItem(tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT); splash->startDecaying(); } - std::shared_ptr corpse = getCorpse(lastHitCreature, mostDamageCreature); + const auto &corpse = getCorpse(lastHitCreature, mostDamageCreature); if (tile && corpse) { g_game().internalAddItem(tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT); dropLoot(corpse->getContainer(), lastHitCreature); corpse->startDecaying(); - bool disallowedCorpses = corpse->isRewardCorpse() || (corpse->getID() == ITEM_MALE_CORPSE || corpse->getID() == ITEM_FEMALE_CORPSE); - const auto player = mostDamageCreature ? mostDamageCreature->getPlayer() : nullptr; - auto corpseContainer = corpse->getContainer(); + const bool disallowedCorpses = corpse->isRewardCorpse() || (corpse->getID() == ITEM_MALE_CORPSE || corpse->getID() == ITEM_FEMALE_CORPSE); + const auto &player = mostDamageCreature ? mostDamageCreature->getPlayer() : nullptr; + const auto &corpseContainer = corpse->getContainer(); if (corpseContainer && player && !disallowedCorpses) { - auto monster = getMonster(); + const auto &monster = getMonster(); if (monster && !monster->isRewardBoss()) { std::ostringstream lootMessage; auto collorMessage = player->getProtocolVersion() > 1200; @@ -869,7 +681,7 @@ bool Creature::hasBeenAttacked(uint32_t attackerId) { return (OTSYS_TIME() - it->second.ticks) <= g_configManager().getNumber(PZ_LOCKED); } -std::shared_ptr Creature::getCorpse(std::shared_ptr, std::shared_ptr) { +std::shared_ptr Creature::getCorpse(const std::shared_ptr &, const std::shared_ptr &) { if (getLookCorpse() != 0) { return Item::CreateItem(getLookCorpse()); } @@ -901,14 +713,14 @@ void Creature::changeMana(int32_t manaChange) { } } -void Creature::gainHealth(std::shared_ptr healer, int32_t healthGain) { +void Creature::gainHealth(const std::shared_ptr &healer, int32_t healthGain) { changeHealth(healthGain); if (healer) { healer->onTargetCreatureGainHealth(static_self_cast(), healthGain); } } -void Creature::drainHealth(std::shared_ptr attacker, int32_t damage) { +void Creature::drainHealth(const std::shared_ptr &attacker, int32_t damage) { changeHealth(-damage, false); if (attacker) { @@ -916,7 +728,7 @@ void Creature::drainHealth(std::shared_ptr attacker, int32_t damage) { } } -void Creature::drainMana(std::shared_ptr attacker, int32_t manaLoss) { +void Creature::drainMana(const std::shared_ptr &attacker, int32_t manaLoss) { onAttacked(); changeMana(-manaLoss); @@ -939,7 +751,7 @@ void Creature::mitigateDamage(const CombatType_t &combatType, BlockType_t &block } } -void Creature::applyAbsorbDamageModifications(std::shared_ptr attacker, int32_t &damage, CombatType_t combatType) const { +void Creature::applyAbsorbDamageModifications(const std::shared_ptr &attacker, int32_t &damage, CombatType_t combatType) const { if (combatType != COMBAT_HEALING && damage != 0) { int32_t value = getAbsorbPercent(combatType); if (value != 0) { @@ -959,7 +771,7 @@ void Creature::applyAbsorbDamageModifications(std::shared_ptr attacker } } -BlockType_t Creature::blockHit(std::shared_ptr attacker, CombatType_t combatType, int32_t &damage, bool checkDefense /* = false */, bool checkArmor /* = false */, bool /* field = false */) { +BlockType_t Creature::blockHit(const std::shared_ptr &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense /* = false */, bool checkArmor /* = false */, bool /* field = false */) { BlockType_t blockType = BLOCK_NONE; // Apply skills 12.72 absorbs damage @@ -1026,10 +838,10 @@ BlockType_t Creature::blockHit(std::shared_ptr attacker, CombatType_t return blockType; } -bool Creature::setAttackedCreature(std::shared_ptr creature) { +bool Creature::setAttackedCreature(const std::shared_ptr &creature) { if (creature) { - auto monster = getMonster(); - auto tile = getTile(); + const auto &monster = getMonster(); + const auto &tile = getTile(); if (monster && monster->isFamiliar() && tile && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { return false; } @@ -1063,14 +875,14 @@ void Creature::getPathSearchParams(const std::shared_ptr &, FindPathPa void Creature::goToFollowCreature_async(std::function &&onComplete) { if (!hasAsyncTaskFlag(Pathfinder) && onComplete) { - g_dispatcher().context().addEvent(std::move(onComplete), "goToFollowCreature_async"); + g_dispatcher().addEvent(std::move(onComplete), "goToFollowCreature_async"); } setAsyncTaskFlag(Pathfinder, true); } void Creature::goToFollowCreature() { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); const auto &followCreature = getFollowCreature(); if (!followCreature) { return; @@ -1115,17 +927,17 @@ void Creature::goToFollowCreature() { } } -bool Creature::canFollowMaster() { - auto master = getMaster(); +bool Creature::canFollowMaster() const { + const auto &master = getMaster(); if (!master) { return false; } - auto tile = master->getTile(); + const auto &tile = master->getTile(); return tile && !tile->hasFlag(TILESTATE_PROTECTIONZONE) && (canSeeInvisibility() || !master->isInvisible()); } -bool Creature::setFollowCreature(std::shared_ptr creature) { - metrics::method_latency measure(__METHOD_NAME__); +bool Creature::setFollowCreature(const std::shared_ptr &creature) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (creature) { if (getFollowCreature() == creature) { return true; @@ -1160,15 +972,19 @@ bool Creature::setFollowCreature(std::shared_ptr creature) { return true; } -double Creature::getDamageRatio(std::shared_ptr attacker) const { +double Creature::getDamageRatio(const std::shared_ptr &attacker) const { uint32_t totalDamage = 0; uint32_t attackerDamage = 0; - for (const auto &it : damageMap) { - const CountBlock_t &cb = it.second; - totalDamage += cb.total; - if (it.first == attacker->getID()) { - attackerDamage += cb.total; + for (const auto &[attackerId, damageInfo] : damageMap) { + const auto &[totalDamageValue, ticks] = damageInfo; + if (attackerId == 0 || totalDamageValue == 0) { + continue; + } + + totalDamage += totalDamageValue; + if (attackerId == attacker->getID()) { + attackerDamage += totalDamageValue; } } @@ -1179,11 +995,11 @@ double Creature::getDamageRatio(std::shared_ptr attacker) const { return (static_cast(attackerDamage) / totalDamage); } -uint64_t Creature::getGainedExperience(std::shared_ptr attacker) const { - return std::floor(getDamageRatio(std::move(attacker)) * getLostExperience()); +uint64_t Creature::getGainedExperience(const std::shared_ptr &attacker) const { + return std::floor(getDamageRatio(attacker) * getLostExperience()); } -void Creature::addDamagePoints(std::shared_ptr attacker, int32_t damagePoints) { +void Creature::addDamagePoints(const std::shared_ptr &attacker, int32_t damagePoints) { if (damagePoints <= 0) { return; } @@ -1221,8 +1037,8 @@ void Creature::onEndCondition(ConditionType_t) { } void Creature::onTickCondition(ConditionType_t type, bool &bRemove) { - auto tile = getTile(); - std::shared_ptr field = tile ? tile->getFieldItem() : nullptr; + const auto &tile = getTile(); + const auto &field = tile ? tile->getFieldItem() : nullptr; if (!field) { return; } @@ -1257,29 +1073,29 @@ void Creature::onTickCondition(ConditionType_t type, bool &bRemove) { } } -void Creature::onCombatRemoveCondition(std::shared_ptr condition) { - removeCondition(std::move(condition)); +void Creature::onCombatRemoveCondition(const std::shared_ptr &condition) { + removeCondition(condition); } void Creature::onAttacked() { // } -void Creature::onAttackedCreatureDrainHealth(std::shared_ptr target, int32_t points) { +void Creature::onAttackedCreatureDrainHealth(const std::shared_ptr &target, int32_t points) { target->addDamagePoints(static_self_cast(), points); } -void Creature::onAttackedCreatureKilled(std::shared_ptr target) { - metrics::method_latency measure(__METHOD_NAME__); +void Creature::onAttackedCreatureKilled(const std::shared_ptr &target) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (target != getCreature()) { uint64_t gainExp = target->getGainedExperience(static_self_cast()); onGainExperience(gainExp, target); } } -bool Creature::deprecatedOnKilledCreature(std::shared_ptr target, bool lastHit) { - metrics::method_latency measure(__METHOD_NAME__); - auto master = getMaster(); +bool Creature::deprecatedOnKilledCreature(const std::shared_ptr &target, bool lastHit) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &master = getMaster(); if (master) { master->deprecatedOnKilledCreature(target, lastHit); } @@ -1292,19 +1108,19 @@ bool Creature::deprecatedOnKilledCreature(std::shared_ptr target, bool return false; } -void Creature::onGainExperience(uint64_t gainExp, std::shared_ptr target) { - metrics::method_latency measure(__METHOD_NAME__); - auto master = getMaster(); +void Creature::onGainExperience(uint64_t gainExp, const std::shared_ptr &target) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &master = getMaster(); if (gainExp == 0 || !master) { return; } - std::shared_ptr m = getMonster(); + const auto &m = getMonster(); if (!m->isFamiliar()) { gainExp /= 2; } - master->onGainExperience(gainExp, std::move(target)); + master->onGainExperience(gainExp, target); if (!m->isFamiliar()) { auto spectators = Spectators().find(position); @@ -1323,11 +1139,11 @@ void Creature::onGainExperience(uint64_t gainExp, std::shared_ptr targ } } -bool Creature::setMaster(std::shared_ptr newMaster, bool reloadCreature /* = false*/) { - metrics::method_latency measure(__METHOD_NAME__); +bool Creature::setMaster(const std::shared_ptr &newMaster, bool reloadCreature /* = false*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); // Persists if this creature has ever been a summon this->summoned = true; - auto oldMaster = getMaster(); + const auto &oldMaster = getMaster(); if (!newMaster && !oldMaster) { return false; @@ -1348,7 +1164,7 @@ bool Creature::setMaster(std::shared_ptr newMaster, bool reloadCreatur m_master = newMaster; if (oldMaster) { - const auto &it = std::ranges::find(oldMaster->m_summons, self); + auto it = std::ranges::find(oldMaster->m_summons, self); if (it != oldMaster->m_summons.end()) { oldMaster->m_summons.erase(it); } @@ -1356,22 +1172,22 @@ bool Creature::setMaster(std::shared_ptr newMaster, bool reloadCreatur return true; } -bool Creature::addCondition(std::shared_ptr condition, bool attackerPlayer /* = false*/) { - metrics::method_latency measure(__METHOD_NAME__); +bool Creature::addCondition(const std::shared_ptr &condition, bool attackerPlayer /* = false*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (condition == nullptr) { return false; } if (isSuppress(condition->getType(), attackerPlayer)) { return false; } - std::shared_ptr prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId()); + const auto &prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId()); if (prevCond) { prevCond->addCondition(getCreature(), condition); return true; } if (condition->startCondition(getCreature())) { - conditions.push_back(condition); + conditions.emplace_back(condition); onAddCondition(condition->getType()); return true; } @@ -1379,8 +1195,11 @@ bool Creature::addCondition(std::shared_ptr condition, bool attackerP return false; } -bool Creature::addCombatCondition(std::shared_ptr condition, bool attackerPlayer /* = false*/) { - // Caution: condition variable could be deleted after the call to addCondition +bool Creature::addCombatCondition(const std::shared_ptr &condition, bool attackerPlayer /* = false*/) { + if (condition == nullptr) { + return false; + } + ConditionType_t type = condition->getType(); if (!addCondition(condition, attackerPlayer)) { @@ -1392,7 +1211,7 @@ bool Creature::addCombatCondition(std::shared_ptr condition, bool att } void Creature::removeCondition(ConditionType_t type) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); auto it = conditions.begin(), end = conditions.end(); while (it != end) { std::shared_ptr condition = *it; @@ -1410,10 +1229,11 @@ void Creature::removeCondition(ConditionType_t type) { } void Creature::removeCondition(ConditionType_t conditionType, ConditionId_t conditionId, bool force /* = false*/) { - metrics::method_latency measure(__METHOD_NAME__); - auto it = conditions.begin(), end = conditions.end(); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + auto it = conditions.begin(); + const auto end = conditions.end(); while (it != end) { - std::shared_ptr condition = *it; + auto condition = *it; if (condition->getType() != conditionType || condition->getId() != conditionId) { ++it; continue; @@ -1441,7 +1261,7 @@ void Creature::removeCombatCondition(ConditionType_t type) { std::vector> removeConditions; for (const auto &condition : conditions) { if (condition->getType() == type) { - removeConditions.push_back(condition); + removeConditions.emplace_back(condition); } } @@ -1450,8 +1270,8 @@ void Creature::removeCombatCondition(ConditionType_t type) { } } -void Creature::removeCondition(std::shared_ptr condition) { - auto it = std::find(conditions.begin(), conditions.end(), condition); +void Creature::removeCondition(const std::shared_ptr &condition) { + const auto it = std::ranges::find(conditions, condition); if (it == conditions.end()) { return; } @@ -1472,7 +1292,7 @@ std::shared_ptr Creature::getCondition(ConditionType_t type) const { } std::shared_ptr Creature::getCondition(ConditionType_t type, ConditionId_t conditionId, uint32_t subId /* = 0*/) const { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); for (const auto &condition : conditions) { if (condition->getType() == type && condition->getId() == conditionId && condition->getSubId() == subId) { return condition; @@ -1485,14 +1305,14 @@ std::vector> Creature::getConditionsByType(ConditionT std::vector> conditionsVec; for (const auto &condition : conditions) { if (condition->getType() == type) { - conditionsVec.push_back(condition); + conditionsVec.emplace_back(condition); } } return conditionsVec; } void Creature::executeConditions(uint32_t interval) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); auto it = conditions.begin(), end = conditions.end(); while (it != end) { std::shared_ptr condition = *it; @@ -1511,7 +1331,7 @@ void Creature::executeConditions(uint32_t interval) { } bool Creature::hasCondition(ConditionType_t type, uint32_t subId /* = 0*/) const { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (isSuppress(type, false)) { return false; } @@ -1565,6 +1385,10 @@ LightInfo Creature::getCreatureLight() const { return internalLight; } +uint16_t Creature::getSpeed() const { + return std::clamp(baseSpeed + varSpeed, 0, static_cast(std::numeric_limits::max())); +} + void Creature::setSpeed(int32_t varSpeedDelta) { // Prevents creatures from not exceeding the maximum allowed speed if (getSpeed() >= PLAYER_MAX_SPEED) { @@ -1593,7 +1417,7 @@ void Creature::setNormalCreatureLight() { } bool Creature::registerCreatureEvent(const std::string &name) { - const auto event = g_creatureEvents().getEventByName(name); + const auto &event = g_creatureEvents().getEventByName(name); if (!event) { return false; } @@ -1609,12 +1433,12 @@ bool Creature::registerCreatureEvent(const std::string &name) { scriptEventsBitField |= static_cast(1) << type; } - eventsList.push_back(event); + eventsList.emplace_back(event); return true; } bool Creature::unregisterCreatureEvent(const std::string &name) { - const auto event = g_creatureEvents().getEventByName(name); + const auto &event = g_creatureEvents().getEventByName(name); if (!event) { return false; } @@ -1646,7 +1470,38 @@ bool Creature::unregisterCreatureEvent(const std::string &name) { return true; } -CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) { +std::shared_ptr Creature::getParent() { + return getTile(); +} + +void Creature::setParent(std::weak_ptr cylinder) { + const auto oldGroundSpeed = walk.groundSpeed; + walk.groundSpeed = 150; + + if (const auto &lockedCylinder = cylinder.lock()) { + const auto &newParent = lockedCylinder->getTile(); + position = newParent->getPosition(); + m_tile = newParent; + + if (newParent->getGround()) { + const auto &it = Item::items[newParent->getGround()->getID()]; + if (it.speed > 0) { + walk.groundSpeed = it.speed; + } + } + } + + if (walk.groundSpeed != oldGroundSpeed) { + walk.recache(); + } +} + +// creature script events +bool Creature::hasEventRegistered(CreatureEventType_t event) const { + return (0 != (scriptEventsBitField & (static_cast(1) << event))); +} + +CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) const { CreatureEventList tmpEventList; if (!hasEventRegistered(type)) { @@ -1655,7 +1510,7 @@ CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) { for (const auto &creatureEventPtr : eventsList) { if (creatureEventPtr->getEventType() == type) { - tmpEventList.push_back(creatureEventPtr); + tmpEventList.emplace_back(creatureEventPtr); } } @@ -1728,8 +1583,7 @@ bool FrozenPathingConditionCall::operator()(const Position &startPos, const Posi if (testDist == fpp.maxTargetDist) { bestMatchDist = 0; return true; - } else if (testDist > bestMatchDist) { - // not quite what we want, but the best so far + } else if (testDist > bestMatchDist) { // not quite what we want, but the best so far bestMatchDist = testDist; return true; } @@ -1738,14 +1592,22 @@ bool FrozenPathingConditionCall::operator()(const Position &startPos, const Posi } bool Creature::isInvisible() const { - return std::find_if(conditions.begin(), conditions.end(), [](const std::shared_ptr &condition) { + return std::ranges::find_if(conditions, [](const std::shared_ptr &condition) { return condition->getType() == CONDITION_INVISIBLE; }) != conditions.end(); } +ZoneType_t Creature::getZoneType() { + if (getTile()) { + return getTile()->getZoneType(); + } + + return ZONE_NORMAL; +} + bool Creature::getPathTo(const Position &targetPos, std::vector &dirList, const FindPathParams &fpp) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (fpp.maxSearchDist != 0 || fpp.keepDistance) { return g_game().map.getPathMatchingCond(getCreature(), targetPos, dirList, FrozenPathingConditionCall(targetPos), fpp); } @@ -1762,7 +1624,7 @@ bool Creature::getPathTo(const Position &targetPos, std::vector &dirL return getPathTo(targetPos, dirList, fpp); } -void Creature::turnToCreature(std::shared_ptr creature) { +void Creature::turnToCreature(const std::shared_ptr &creature) { const Position &creaturePos = creature->getPosition(); const auto dx = Position::getOffsetX(position, creaturePos); const auto dy = Position::getOffsetY(position, creaturePos); @@ -1901,7 +1763,7 @@ std::unordered_set> Creature::getZones() { } void Creature::iconChanged() { - auto tile = getTile(); + const auto &tile = getTile(); if (!tile) { return; } @@ -1937,3 +1799,18 @@ void Creature::sendAsyncTasks() { }, TaskGroup::WalkParallel); } + +void Creature::safeCall(std::function &&action) const { + if (g_dispatcher().context().isAsync()) { + g_dispatcher().addEvent([weak_self = std::weak_ptr(static_self_cast()), action = std::move(action)] { + if (const auto self = weak_self.lock()) { + if (!self->isInternalRemoved) { + action(); + } + } + }, + g_dispatcher().context().getName()); + } else if (!isInternalRemoved) { + action(); + } +} diff --git a/src/creatures/creature.hpp b/src/creatures/creature.hpp index eea144448ba..fcea0a6b0f2 100644 --- a/src/creatures/creature.hpp +++ b/src/creatures/creature.hpp @@ -9,19 +9,16 @@ #pragma once -#include "declarations.hpp" -#include "creatures/combat/condition.hpp" -#include "utils/utils_definitions.hpp" -#include "lua/creature/creatureevent.hpp" -#include "map/map.hpp" +#include "creatures/creatures_definitions.hpp" +#include "game/game_definitions.hpp" #include "game/movement/position.hpp" -#include "items/tile.hpp" - -using ConditionList = std::list>; -using CreatureEventList = std::list>; +#include "items/thing.hpp" +#include "map/map_const.hpp" +#include "utils/utils_definitions.hpp" +class CreatureEvent; +class Condition; class Map; -class Thing; class Container; class Player; class Monster; @@ -29,6 +26,19 @@ class Npc; class Item; class Tile; class Zone; +class MonsterType; +class Cylinder; +class ItemType; + +struct CreatureIcon; +struct Position; + +enum CreatureType_t : uint8_t; +enum ZoneType_t : uint8_t; +enum CreatureEventType_t : uint8_t; + +using ConditionList = std::list>; +using CreatureEventList = std::list>; static constexpr uint8_t WALK_TARGET_NEARBY_EXTRA_COST = 2; static constexpr uint8_t WALK_FLOOR_CHANGE_EXTRA_COST = 2; @@ -40,7 +50,7 @@ static constexpr int32_t EVENT_CHECK_CREATURE_INTERVAL = (EVENT_CREATURE_THINK_I class FrozenPathingConditionCall { public: explicit FrozenPathingConditionCall(Position newTargetPos) : - targetPos(std::move(newTargetPos)) { } + targetPos(newTargetPos) { } bool operator()(const Position &startPos, const Position &testPos, const FindPathParams &fpp, int32_t &bestMatchDist) const; @@ -79,7 +89,7 @@ class Creature : virtual public Thing, public SharedObject { std::shared_ptr getCreature() const override final { return static_self_cast(); } - virtual std::shared_ptr getPlayer() { + std::shared_ptr getPlayer() override { return nullptr; } virtual std::shared_ptr getPlayer() const { @@ -117,7 +127,7 @@ class Creature : virtual public Thing, public SharedObject { virtual void addList() = 0; virtual bool canSee(const Position &pos); - virtual bool canSeeCreature(std::shared_ptr creature) const; + virtual bool canSeeCreature(const std::shared_ptr &creature) const; virtual RaceType_t getRace() const { return RACE_NONE; @@ -125,7 +135,7 @@ class Creature : virtual public Thing, public SharedObject { virtual Skulls_t getSkull() const { return skull; } - virtual Skulls_t getSkullClient(std::shared_ptr creature) { + virtual Skulls_t getSkullClient(const std::shared_ptr &creature) { return creature->getSkull(); } void setSkull(Skulls_t newSkull); @@ -184,9 +194,7 @@ class Creature : virtual public Thing, public SharedObject { virtual uint16_t getStepSpeed() const { return getSpeed(); } - uint16_t getSpeed() const { - return static_cast(baseSpeed + varSpeed); - } + uint16_t getSpeed() const; void setSpeed(int32_t varSpeedDelta); void setBaseSpeed(uint16_t newBaseSpeed) { @@ -295,13 +303,7 @@ class Creature : virtual public Thing, public SharedObject { return outfit == 75 || outfit == 266 || outfit == 302; } bool isInvisible() const; - ZoneType_t getZoneType() { - if (getTile()) { - return getTile()->getZoneType(); - } - - return ZONE_NORMAL; - } + ZoneType_t getZoneType(); std::unordered_set> getZones(); @@ -322,7 +324,7 @@ class Creature : virtual public Thing, public SharedObject { std::shared_ptr getFollowCreature() const { return m_followCreature.lock(); } - virtual bool setFollowCreature(std::shared_ptr creature); + virtual bool setFollowCreature(const std::shared_ptr &creature); // follow events virtual void onFollowCreature(const std::shared_ptr &) { @@ -333,10 +335,10 @@ class Creature : virtual public Thing, public SharedObject { } // combat functions - std::shared_ptr getAttackedCreature() { + std::shared_ptr getAttackedCreature() const { return m_attackedCreature.lock(); } - virtual bool setAttackedCreature(std::shared_ptr creature); + virtual bool setAttackedCreature(const std::shared_ptr &creature); /** * @brief Mitigates damage inflicted on a creature. @@ -351,11 +353,11 @@ class Creature : virtual public Thing, public SharedObject { * @param damage Reference to the amount of damage inflicted, which will be reduced by the creature's mitigation factor. */ void mitigateDamage(const CombatType_t &combatType, BlockType_t &blockType, int32_t &damage) const; - virtual BlockType_t blockHit(std::shared_ptr attacker, CombatType_t combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false); + virtual BlockType_t blockHit(const std::shared_ptr &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false); - void applyAbsorbDamageModifications(std::shared_ptr attacker, int32_t &damage, CombatType_t combatType) const; + void applyAbsorbDamageModifications(const std::shared_ptr &attacker, int32_t &damage, CombatType_t combatType) const; - bool setMaster(std::shared_ptr newMaster, bool reloadCreature = false); + bool setMaster(const std::shared_ptr &newMaster, bool reloadCreature = false); void removeMaster() { if (getMaster()) { @@ -401,11 +403,11 @@ class Creature : virtual public Thing, public SharedObject { return SPEECHBUBBLE_NONE; } - bool addCondition(std::shared_ptr condition, bool attackerPlayer = false); - bool addCombatCondition(std::shared_ptr condition, bool attackerPlayer = false); + bool addCondition(const std::shared_ptr &condition, bool attackerPlayer = false); + bool addCombatCondition(const std::shared_ptr &condition, bool attackerPlayer = false); void removeCondition(ConditionType_t conditionType, ConditionId_t conditionId, bool force = false); void removeCondition(ConditionType_t type); - void removeCondition(std::shared_ptr condition); + void removeCondition(const std::shared_ptr &condition); void removeCombatCondition(ConditionType_t type); std::shared_ptr getCondition(ConditionType_t type) const; std::shared_ptr getCondition(ConditionType_t type, ConditionId_t conditionId, uint32_t subId = 0) const; @@ -433,17 +435,17 @@ class Creature : virtual public Thing, public SharedObject { virtual void changeHealth(int32_t healthChange, bool sendHealthChange = true); virtual void changeMana(int32_t manaChange); - void gainHealth(std::shared_ptr attacker, int32_t healthGain); - virtual void drainHealth(std::shared_ptr attacker, int32_t damage); - virtual void drainMana(std::shared_ptr attacker, int32_t manaLoss); + void gainHealth(const std::shared_ptr &attacker, int32_t healthGain); + virtual void drainHealth(const std::shared_ptr &attacker, int32_t damage); + virtual void drainMana(const std::shared_ptr &attacker, int32_t manaLoss); - virtual bool challengeCreature(std::shared_ptr, [[maybe_unused]] int targetChangeCooldown) { + virtual bool challengeCreature(const std::shared_ptr &, [[maybe_unused]] int targetChangeCooldown) { return false; } void onDeath(); - virtual uint64_t getGainedExperience(std::shared_ptr attacker) const; - void addDamagePoints(std::shared_ptr attacker, int32_t damagePoints); + virtual uint64_t getGainedExperience(const std::shared_ptr &attacker) const; + void addDamagePoints(const std::shared_ptr &attacker, int32_t damagePoints); bool hasBeenAttacked(uint32_t attackerId); // combat event functions @@ -451,26 +453,26 @@ class Creature : virtual public Thing, public SharedObject { virtual void onAddCombatCondition(ConditionType_t type); virtual void onEndCondition(ConditionType_t type); void onTickCondition(ConditionType_t type, bool &bRemove); - virtual void onCombatRemoveCondition(std::shared_ptr condition); - virtual void onAttackedCreature(std::shared_ptr) { } + virtual void onCombatRemoveCondition(const std::shared_ptr &condition); + virtual void onAttackedCreature(const std::shared_ptr &) { } virtual void onAttacked(); - virtual void onAttackedCreatureDrainHealth(std::shared_ptr target, int32_t points); - virtual void onTargetCreatureGainHealth(std::shared_ptr, int32_t) { } - void onAttackedCreatureKilled(std::shared_ptr target); + virtual void onAttackedCreatureDrainHealth(const std::shared_ptr &target, int32_t points); + virtual void onTargetCreatureGainHealth(const std::shared_ptr &, int32_t) { } + void onAttackedCreatureKilled(const std::shared_ptr &target); /** * @deprecated -- This is here to trigger the deprecated onKill events in lua */ - bool deprecatedOnKilledCreature(std::shared_ptr target, bool lastHit); + bool deprecatedOnKilledCreature(const std::shared_ptr &target, bool lastHit); virtual bool onKilledPlayer([[maybe_unused]] const std::shared_ptr &target, [[maybe_unused]] bool lastHit) { return false; }; virtual bool onKilledMonster([[maybe_unused]] const std::shared_ptr &target) { return false; }; - virtual void onGainExperience(uint64_t gainExp, std::shared_ptr target); - virtual void onAttackedCreatureBlockHit(BlockType_t) { } + virtual void onGainExperience(uint64_t gainExp, const std::shared_ptr &target); + virtual void onAttackedCreatureBlockHit(const BlockType_t &) { } virtual void onBlockHit() { } - virtual void onTakeDamage(std::shared_ptr, int32_t) { } + virtual void onTakeDamage(const std::shared_ptr &, int32_t) { } virtual void onChangeZone(ZoneType_t zone); virtual void onAttackedCreatureChangeZone(ZoneType_t zone); virtual void onIdleStatus(); @@ -484,14 +486,14 @@ class Creature : virtual public Thing, public SharedObject { virtual void onCreatureWalk(); virtual bool getNextStep(Direction &dir, uint32_t &flags); - virtual void turnToCreature(std::shared_ptr creature); + virtual void turnToCreature(const std::shared_ptr &creature); - void onAddTileItem(std::shared_ptr tile, const Position &pos); - virtual void onUpdateTileItem(std::shared_ptr tile, const Position &pos, std::shared_ptr oldItem, const ItemType &oldType, std::shared_ptr newItem, const ItemType &newType); - virtual void onRemoveTileItem(std::shared_ptr tile, const Position &pos, const ItemType &iType, std::shared_ptr item); + void onAddTileItem(const std::shared_ptr & /*tile*/, const Position & /*pos*/) { } + virtual void onUpdateTileItem(const std::shared_ptr &tile, const Position &pos, const std::shared_ptr &oldItem, const ItemType &oldType, const std::shared_ptr &newItem, const ItemType &newType) { } + virtual void onRemoveTileItem(const std::shared_ptr &tile, const Position &pos, const ItemType &iType, const std::shared_ptr &item) { } - virtual void onCreatureAppear(std::shared_ptr creature, bool isLogin); - virtual void onRemoveCreature(std::shared_ptr creature, bool isLogout); + virtual void onCreatureAppear(const std::shared_ptr &creature, bool isLogin); + virtual void onRemoveCreature(const std::shared_ptr &creature, bool isLogout); /** * @brief Check if the summon can move/spawn and if the familiar can teleport to the master @@ -507,7 +509,7 @@ class Creature : virtual public Thing, public SharedObject { virtual void onAttackedCreatureDisappear(bool) { } virtual void onFollowCreatureDisappear(bool) { } - virtual void onCreatureSay(std::shared_ptr, SpeakClasses, const std::string &) { } + virtual void onCreatureSay(const std::shared_ptr &, SpeakClasses, const std::string &) { } virtual void onPlacedCreature() { } @@ -546,31 +548,9 @@ class Creature : virtual public Thing, public SharedObject { bool registerCreatureEvent(const std::string &name); bool unregisterCreatureEvent(const std::string &name); - std::shared_ptr getParent() override final { - return getTile(); - } + std::shared_ptr getParent() final; - void setParent(std::weak_ptr cylinder) override final { - const auto oldGroundSpeed = walk.groundSpeed; - walk.groundSpeed = 150; - - if (const auto &lockedCylinder = cylinder.lock()) { - const auto &newParent = lockedCylinder->getTile(); - position = newParent->getPosition(); - m_tile = newParent; - - if (newParent->getGround()) { - const auto &it = Item::items[newParent->getGround()->getID()]; - if (it.speed > 0) { - walk.groundSpeed = it.speed; - } - } - } - - if (walk.groundSpeed != oldGroundSpeed) { - walk.recache(); - } - } + void setParent(std::weak_ptr cylinder) final; const Position &getPosition() override final { return position; @@ -580,8 +560,6 @@ class Creature : virtual public Thing, public SharedObject { return m_tile.lock(); } - int32_t getWalkCache(const Position &pos); - const Position &getLastPosition() const { return lastPosition; } @@ -591,7 +569,7 @@ class Creature : virtual public Thing, public SharedObject { static bool canSee(const Position &myPos, const Position &pos, int32_t viewRangeX, int32_t viewRangeY); - double getDamageRatio(std::shared_ptr attacker) const; + double getDamageRatio(const std::shared_ptr &attacker) const; bool getPathTo(const Position &targetPos, std::vector &dirList, const FindPathParams &fpp); bool getPathTo(const Position &targetPos, std::vector &dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch = true, bool clearSight = true, int32_t maxSearchDist = 7); @@ -719,19 +697,10 @@ class Creature : virtual public Thing, public SharedObject { Pathfinder = 1 << 3 }; - virtual bool useCacheMap() const { - return false; - } - virtual bool isDead() const { return false; } - static constexpr int32_t mapWalkWidth = MAP_MAX_VIEW_PORT_X * 2 + 1; - static constexpr int32_t mapWalkHeight = MAP_MAX_VIEW_PORT_Y * 2 + 1; - static constexpr int32_t maxWalkCacheWidth = (mapWalkWidth - 1) / 2; - static constexpr int32_t maxWalkCacheHeight = (mapWalkHeight - 1) / 2; - Position position; CountMap damageMap; @@ -795,9 +764,7 @@ class Creature : virtual public Thing, public SharedObject { std::atomic_bool creatureCheck = false; std::atomic_bool inCheckCreaturesVector = false; - bool localMapCache[mapWalkHeight][mapWalkWidth] = { { false } }; bool isInternalRemoved = false; - bool isMapLoaded = false; bool isUpdatingPath = false; bool skillLoss = true; bool lootDrop = true; @@ -818,15 +785,10 @@ class Creature : virtual public Thing, public SharedObject { std::map creatureIcons = {}; // creature script events - bool hasEventRegistered(CreatureEventType_t event) const { - return (0 != (scriptEventsBitField & (static_cast(1) << event))); - } - CreatureEventList getCreatureEvents(CreatureEventType_t type); + bool hasEventRegistered(CreatureEventType_t event) const; + CreatureEventList getCreatureEvents(CreatureEventType_t type) const; - void updateMapCache(); - void updateTileCache(std::shared_ptr tile, int32_t dx, int32_t dy); - void updateTileCache(std::shared_ptr tile, const Position &pos); - void onCreatureDisappear(std::shared_ptr creature, bool isLogout); + void onCreatureDisappear(const std::shared_ptr &creature, bool isLogout); virtual void doAttacking(uint32_t) { } virtual bool hasExtraSwing() { return false; @@ -835,14 +797,14 @@ class Creature : virtual public Thing, public SharedObject { virtual uint64_t getLostExperience() const { return 0; } - virtual void dropLoot(std::shared_ptr, std::shared_ptr) { } + virtual void dropLoot(const std::shared_ptr &, const std::shared_ptr &) { } virtual uint16_t getLookCorpse() const { return 0; } virtual void getPathSearchParams(const std::shared_ptr &, FindPathParams &fpp); - virtual void death(std::shared_ptr) { } - virtual bool dropCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified); - virtual std::shared_ptr getCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature); + virtual void death(const std::shared_ptr &) { } + virtual bool dropCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified); + virtual std::shared_ptr getCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature); friend class Game; friend class Map; @@ -868,8 +830,11 @@ class Creature : virtual public Thing, public SharedObject { virtual void onExecuteAsyncTasks() {}; + // This method maintains safety in asynchronous calls, avoiding competition between threads. + void safeCall(std::function &&action) const; + private: - bool canFollowMaster(); + bool canFollowMaster() const; bool isLostSummon(); void sendAsyncTasks(); void handleLostSummon(bool teleportSummons); diff --git a/src/creatures/creatures_definitions.hpp b/src/creatures/creatures_definitions.hpp index 9594a704eed..dd554c086b3 100644 --- a/src/creatures/creatures_definitions.hpp +++ b/src/creatures/creatures_definitions.hpp @@ -11,6 +11,7 @@ #ifndef USE_PRECOMPILED_HEADERS #include + #include #include #include #include @@ -705,6 +706,8 @@ enum SpellGroup_t : uint8_t { SPELLGROUP_CRIPPLING = 6, SPELLGROUP_FOCUS = 7, SPELLGROUP_ULTIMATESTRIKES = 8, + SPELLGROUP_BURSTS_OF_NATURE = 9, + SPELLGROUP_GREAT_BEAMS = 10, }; enum ChannelEvent_t : uint8_t { @@ -1368,7 +1371,7 @@ struct CreatureIcon { explicit constexpr CreatureIcon(CreatureIconQuests_t quest, uint16_t count = 0) : category(CreatureIconCategory_t::Quests), quest(quest), count(count) { } - CreatureIconCategory_t category; + CreatureIconCategory_t category {}; CreatureIconModifications_t modification = CreatureIconModifications_t::None; CreatureIconQuests_t quest = CreatureIconQuests_t::None; uint16_t count = 0; @@ -1397,7 +1400,7 @@ struct CreatureIcon { struct Position; struct VIPEntry { - VIPEntry(uint32_t initGuid, const std::string &initName, const std::string &initDescription, uint32_t initIcon, bool initNotify) : + VIPEntry(uint32_t initGuid, std::string initName, std::string initDescription, uint32_t initIcon, bool initNotify) : guid(initGuid), name(std::move(initName)), description(std::move(initDescription)), @@ -1405,20 +1408,20 @@ struct VIPEntry { notify(initNotify) { } uint32_t guid = 0; - std::string name = ""; - std::string description = ""; + std::string name; + std::string description; uint32_t icon = 0; bool notify = false; }; struct VIPGroupEntry { - VIPGroupEntry(uint8_t initId, const std::string &initName, bool initCustomizable) : + VIPGroupEntry(uint8_t initId, std::string initName, bool initCustomizable) : id(initId), name(std::move(initName)), customizable(initCustomizable) { } uint8_t id = 0; - std::string name = ""; + std::string name; bool customizable = false; }; @@ -1485,7 +1488,7 @@ struct MarketOffer { struct MarketOfferEx { MarketOfferEx() = default; - MarketOfferEx(MarketOfferEx &&other) : + MarketOfferEx(MarketOfferEx &&other) noexcept : id(other.id), playerId(other.playerId), timestamp(other.timestamp), @@ -1497,15 +1500,15 @@ struct MarketOfferEx { tier(other.tier), playerName(std::move(other.playerName)) { } - uint32_t id; - uint32_t playerId; - uint32_t timestamp; - uint64_t price; - uint16_t amount; - uint16_t counter; - uint16_t itemId; - MarketAction_t type; - uint8_t tier; + uint32_t id {}; + uint32_t playerId {}; + uint32_t timestamp {}; + uint64_t price {}; + uint16_t amount {}; + uint16_t counter {}; + uint16_t itemId {}; + MarketAction_t type {}; + uint8_t tier {}; std::string playerName; }; @@ -1583,8 +1586,6 @@ struct RespawnType { bool underground; }; -struct LootBlock; - struct LootBlock { uint16_t id; uint32_t countmax; @@ -1625,17 +1626,16 @@ struct LootBlock { }; struct ShopBlock { - uint16_t itemId; + uint16_t itemId {}; std::string itemName; - int32_t itemSubType; - uint32_t itemBuyPrice; - uint32_t itemSellPrice; - int32_t itemStorageKey; - int32_t itemStorageValue; + int32_t itemSubType {}; + uint32_t itemBuyPrice {}; + uint32_t itemSellPrice {}; + int32_t itemStorageKey {}; + int32_t itemStorageValue {}; std::vector childShop; - ShopBlock() : - itemId(0), itemName(""), itemSubType(0), itemBuyPrice(0), itemSellPrice(0), itemStorageKey(0), itemStorageValue(0) { } + ShopBlock() = default; explicit ShopBlock(uint16_t newItemId, std::string newName = "", int32_t newSubType = 0, uint32_t newBuyPrice = 0, uint32_t newSellPrice = 0, int32_t newStorageKey = 0, int32_t newStorageValue = 0) : itemId(newItemId), itemName(std::move(newName)), itemSubType(newSubType), itemBuyPrice(newBuyPrice), itemSellPrice(newSellPrice), itemStorageKey(newStorageKey), itemStorageValue(newStorageValue) { } diff --git a/src/creatures/interactions/chat.cpp b/src/creatures/interactions/chat.cpp index 9b73e6caad8..326b2555128 100644 --- a/src/creatures/interactions/chat.cpp +++ b/src/creatures/interactions/chat.cpp @@ -8,15 +8,30 @@ */ #include "creatures/interactions/chat.hpp" + +#include "config/configmanager.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "utils/pugicast.hpp" #include "game/scheduling/dispatcher.hpp" +#include "lib/di/container.hpp" +#include "utils/pugicast.hpp" + +PrivateChatChannel::PrivateChatChannel(uint16_t channelId, std::string channelName) : + ChatChannel(channelId, std::move(channelName)) { } + +uint32_t PrivateChatChannel::getOwner() const { + return owner; +} + +void PrivateChatChannel::setOwner(uint32_t newOwner) { + this->owner = newOwner; +} bool PrivateChatChannel::isInvited(uint32_t guid) const { if (guid == getOwner()) { return true; } - return invites.find(guid) != invites.end(); + return invites.contains(guid); } bool PrivateChatChannel::removeInvite(uint32_t guid) { @@ -24,8 +39,8 @@ bool PrivateChatChannel::removeInvite(uint32_t guid) { } void PrivateChatChannel::invitePlayer(const std::shared_ptr &player, const std::shared_ptr &invitePlayer) { - auto result = invites.emplace(invitePlayer->getGUID(), invitePlayer); - if (!result.second) { + auto [iter, inserted] = invites.try_emplace(invitePlayer->getGUID(), invitePlayer); + if (!inserted) { return; } @@ -37,8 +52,12 @@ void PrivateChatChannel::invitePlayer(const std::shared_ptr &player, con ss << invitePlayer->getName() << " has been invited."; player->sendTextMessage(MESSAGE_PARTY_MANAGEMENT, ss.str()); - for (const auto &it : users) { - it.second->sendChannelEvent(id, invitePlayer->getName(), CHANNELEVENT_INVITE); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0 || !playerUser) { + continue; + } + + playerUser->sendChannelEvent(id, invitePlayer->getName(), CHANNELEVENT_INVITE); } } @@ -55,19 +74,35 @@ void PrivateChatChannel::excludePlayer(const std::shared_ptr &player, co excludePlayer->sendClosePrivate(id); - for (const auto &it : users) { - it.second->sendChannelEvent(id, excludePlayer->getName(), CHANNELEVENT_EXCLUDE); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendChannelEvent(id, excludePlayer->getName(), CHANNELEVENT_EXCLUDE); } } void PrivateChatChannel::closeChannel() const { - for (const auto &it : users) { - it.second->sendClosePrivate(id); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendClosePrivate(id); } } +const InvitedMap* PrivateChatChannel::getInvitedUsers() const { + return &invites; +} + +ChatChannel::ChatChannel(uint16_t channelId, std::string channelName) : + name(std::move(channelName)), + id(channelId) { } + bool ChatChannel::addUser(const std::shared_ptr &player) { - if (users.find(player->getID()) != users.end()) { + if (users.contains(player->getID())) { return false; } @@ -77,7 +112,7 @@ bool ChatChannel::addUser(const std::shared_ptr &player) { // TODO: Move to script when guild channels can be scripted if (id == CHANNEL_GUILD) { - const auto guild = player->getGuild(); + const auto &guild = player->getGuild(); if (guild && !guild->getMotd().empty()) { g_dispatcher().scheduleEvent( 150, [playerId = player->getID()] { g_game().sendGuildMotd(playerId); }, "Game::sendGuildMotd" @@ -86,8 +121,12 @@ bool ChatChannel::addUser(const std::shared_ptr &player) { } if (!publicChannel) { - for (const auto &it : users) { - it.second->sendChannelEvent(id, player->getName(), CHANNELEVENT_JOIN); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendChannelEvent(id, player->getName(), CHANNELEVENT_JOIN); } } @@ -104,8 +143,12 @@ bool ChatChannel::removeUser(const std::shared_ptr &player) { users.erase(iter); if (!publicChannel) { - for (const auto &it : users) { - it.second->sendChannelEvent(id, player->getName(), CHANNELEVENT_LEAVE); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendChannelEvent(id, player->getName(), CHANNELEVENT_LEAVE); } } @@ -113,42 +156,74 @@ bool ChatChannel::removeUser(const std::shared_ptr &player) { return true; } -bool ChatChannel::hasUser(const std::shared_ptr &player) { - return users.find(player->getID()) != users.end(); +bool ChatChannel::hasUser(const std::shared_ptr &player) const { + return users.contains(player->getID()); } void ChatChannel::sendToAll(const std::string &message, SpeakClasses type) const { - for (const auto &it : users) { - it.second->sendChannelMessage("", message, type, id); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendChannelMessage("", message, type, id); } } -bool ChatChannel::talk(const std::shared_ptr &fromPlayer, SpeakClasses type, const std::string &text) { - if (users.find(fromPlayer->getID()) == users.end()) { +const std::string &ChatChannel::getName() const { + return name; +} + +uint16_t ChatChannel::getId() const { + return id; +} + +const UsersMap &ChatChannel::getUsers() const { + return users; +} + +const InvitedMap* ChatChannel::getInvitedUsers() const { + return nullptr; +} + +uint32_t ChatChannel::getOwner() const { + return 0; +} + +bool ChatChannel::isPublicChannel() const { + return publicChannel; +} + +bool ChatChannel::talk(const std::shared_ptr &fromPlayer, SpeakClasses type, const std::string &text) const { + if (!users.contains(fromPlayer->getID())) { return false; } - for (const auto &it : users) { - it.second->sendToChannel(fromPlayer, type, text, id); + for (const auto &[playerUserId, playerUser] : users) { + if (playerUserId == 0) { + continue; + } + + playerUser->sendToChannel(fromPlayer, type, text, id); } return true; } -bool ChatChannel::executeCanJoinEvent(const std::shared_ptr &player) { +bool ChatChannel::executeCanJoinEvent(const std::shared_ptr &player) const { if (canJoinEvent == -1) { return true; } // canJoin(player) LuaScriptInterface* scriptInterface = g_chat().getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CanJoinChannelEvent::execute - Player {}, on channel {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(canJoinEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -160,21 +235,21 @@ bool ChatChannel::executeCanJoinEvent(const std::shared_ptr &player) { return scriptInterface->callFunction(1); } -bool ChatChannel::executeOnJoinEvent(const std::shared_ptr &player) { +bool ChatChannel::executeOnJoinEvent(const std::shared_ptr &player) const { if (onJoinEvent == -1) { return true; } // onJoin(player) LuaScriptInterface* scriptInterface = g_chat().getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[OnJoinChannelEvent::execute - Player {}, on channel {}] " "Call stack overflow. Too many lua script calls being nested", player->getName(), getName()); return false; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(onJoinEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -186,21 +261,21 @@ bool ChatChannel::executeOnJoinEvent(const std::shared_ptr &player) { return scriptInterface->callFunction(1); } -bool ChatChannel::executeOnLeaveEvent(const std::shared_ptr &player) { +bool ChatChannel::executeOnLeaveEvent(const std::shared_ptr &player) const { if (onLeaveEvent == -1) { return true; } // onLeave(player) LuaScriptInterface* scriptInterface = g_chat().getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[OnLeaveChannelEvent::execute - Player {}, on channel {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(onLeaveEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -212,21 +287,21 @@ bool ChatChannel::executeOnLeaveEvent(const std::shared_ptr &player) { return scriptInterface->callFunction(1); } -bool ChatChannel::executeOnSpeakEvent(const std::shared_ptr &player, SpeakClasses &type, const std::string &message) { +bool ChatChannel::executeOnSpeakEvent(const std::shared_ptr &player, SpeakClasses &type, const std::string &message) const { if (onSpeakEvent == -1) { return true; } // onSpeak(player, type, message) LuaScriptInterface* scriptInterface = g_chat().getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[OnSpeakChannelEvent::execute - Player {}, type {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), fmt::underlying(type)); return false; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(onSpeakEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -240,7 +315,7 @@ bool ChatChannel::executeOnSpeakEvent(const std::shared_ptr &player, Spe bool result = false; int size0 = lua_gettop(L); - int ret = scriptInterface->protectedCall(L, 3, 1); + int ret = LuaScriptInterface::protectedCall(L, 3, 1); if (ret != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else if (lua_gettop(L) > 0) { @@ -256,7 +331,7 @@ bool ChatChannel::executeOnSpeakEvent(const std::shared_ptr &player, Spe if ((lua_gettop(L) + 4) != size0) { LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } - scriptInterface->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return result; } @@ -266,6 +341,10 @@ Chat::Chat() : scriptInterface.initState(); } +Chat &Chat::getInstance() { + return inject(); +} + bool Chat::load() { pugi::xml_document doc; auto coreFolder = g_configManager().getString(CORE_DIRECTORY); @@ -276,8 +355,8 @@ bool Chat::load() { return false; } - for (auto channelNode : doc.child("channels").children()) { - uint16_t channelId = pugi::cast(channelNode.attribute("id").value()); + for (const auto &channelNode : doc.child("channels").children()) { + auto channelId = pugi::cast(channelNode.attribute("id").value()); std::string channelName = channelNode.attribute("name").as_string(); bool isPublic = channelNode.attribute("public").as_bool(); pugi::xml_attribute scriptAttribute = channelNode.attribute("script"); @@ -300,8 +379,12 @@ bool Chat::load() { } UsersMap tempUserMap = std::move(channel->users); - for (const auto &pair : tempUserMap) { - channel->addUser(pair.second); + for (const auto &[playerUserId, playerUser] : tempUserMap) { + if (playerUserId == 0) { + continue; + } + + channel->addUser(playerUser); } continue; } @@ -332,19 +415,23 @@ std::shared_ptr Chat::createChannel(const std::shared_ptr & switch (channelId) { case CHANNEL_GUILD: { - const auto guild = player->getGuild(); + const auto &guild = player->getGuild(); if (guild != nullptr) { - auto ret = guildChannels.emplace(std::make_pair(guild->getId(), std::make_shared(channelId, guild->getName()))); - return ret.first->second; + auto [iter, inserted] = guildChannels.try_emplace(guild->getId(), std::make_shared(channelId, guild->getName())); + if (inserted) { + return iter->second; + } } break; } case CHANNEL_PARTY: { - auto party = player->getParty(); + const auto &party = player->getParty(); if (party != nullptr) { - auto ret = partyChannels.emplace(std::make_pair(party, std::make_shared(channelId, "Party"))); - return ret.first->second; + auto [iter, inserted] = partyChannels.try_emplace(party, std::make_shared(channelId, "Party")); + if (inserted) { + return iter->second; + } } break; } @@ -357,9 +444,9 @@ std::shared_ptr Chat::createChannel(const std::shared_ptr & // find a free private channel slot for (uint16_t i = 100; i < 10000; ++i) { - auto ret = privateChannels.emplace(std::make_pair(i, std::make_shared(i, player->getName() + "'s Channel"))); - if (ret.second) { // second is a bool that indicates that a new channel has been placed in the map - const auto &newChannel = (*ret.first).second; + auto [iter, inserted] = privateChannels.try_emplace(i, std::make_shared(i, player->getName() + "'s Channel")); + if (inserted) { + const auto &newChannel = iter->second; newChannel->setOwner(player->getGUID()); return newChannel; } @@ -376,7 +463,7 @@ std::shared_ptr Chat::createChannel(const std::shared_ptr & bool Chat::deleteChannel(const std::shared_ptr &player, uint16_t channelId) { switch (channelId) { case CHANNEL_GUILD: { - const auto guild = player->getGuild(); + const auto &guild = player->getGuild(); if (guild == nullptr) { return false; } @@ -391,7 +478,7 @@ bool Chat::deleteChannel(const std::shared_ptr &player, uint16_t channel } case CHANNEL_PARTY: { - auto party = player->getParty(); + const auto &party = player->getParty(); if (party == nullptr) { return false; } @@ -441,16 +528,28 @@ bool Chat::removeUserFromChannel(const std::shared_ptr &player, uint16_t } void Chat::removeUserFromAllChannels(const std::shared_ptr &player) { - for (auto &it : normalChannels) { - it.second->removeUser(player); + for (const auto &[playerUserId, playerUser] : normalChannels) { + if (playerUserId == 0) { + continue; + } + + playerUser->removeUser(player); } - for (auto &it : partyChannels) { - it.second->removeUser(player); + for (const auto &[playerUserId, playerUser] : partyChannels) { + if (playerUserId == 0) { + continue; + } + + playerUser->removeUser(player); } - for (auto &it : guildChannels) { - it.second->removeUser(player); + for (const auto &[playerUserId, playerUser] : guildChannels) { + if (playerUserId == 0) { + continue; + } + + playerUser->removeUser(player); } auto it = privateChannels.begin(); @@ -474,7 +573,7 @@ bool Chat::talkToChannel(const std::shared_ptr &player, SpeakClasses typ } if (channelId == CHANNEL_GUILD) { - GuildRank_ptr rank = player->getGuildRank(); + const auto &rank = player->getGuildRank(); if (rank && rank->level > 1) { type = TALKTYPE_CHANNEL_O; } else if (type != TALKTYPE_CHANNEL_Y) { @@ -496,11 +595,11 @@ ChannelList Chat::getChannelList(const std::shared_ptr &player) { if (player->getGuild()) { auto channel = getChannel(player, CHANNEL_GUILD); if (channel) { - list.push_back(channel); + list.emplace_back(channel); } else { channel = createChannel(player, CHANNEL_GUILD); if (channel) { - list.push_back(channel); + list.emplace_back(channel); } } } @@ -508,28 +607,36 @@ ChannelList Chat::getChannelList(const std::shared_ptr &player) { if (player->getParty()) { auto channel = getChannel(player, CHANNEL_PARTY); if (channel) { - list.push_back(channel); + list.emplace_back(channel); } else { channel = createChannel(player, CHANNEL_PARTY); if (channel) { - list.push_back(channel); + list.emplace_back(channel); } } } - for (const auto &it : normalChannels) { - const auto &channel = getChannel(player, it.first); + for (const auto &[playerUserId, playerUser] : normalChannels) { + if (playerUserId == 0) { + continue; + } + + const auto &channel = getChannel(player, playerUserId); if (channel) { - list.push_back(channel); + list.emplace_back(channel); } } bool hasPrivate = false; - for (auto &it : privateChannels) { - if (const auto &channel = it.second) { - uint32_t guid = player->getGUID(); + for (const auto &[playerUserId, playerUser] : privateChannels) { + if (playerUserId == 0) { + continue; + } + + if (const auto &channel = playerUser) { + const uint32_t guid = player->getGUID(); if (channel->isInvited(guid)) { - list.push_back(channel); + list.emplace_back(channel); } if (channel->getOwner() == guid) { @@ -539,7 +646,7 @@ ChannelList Chat::getChannelList(const std::shared_ptr &player) { } if (!hasPrivate && player->isPremium()) { - list.push_front(dummyPrivate); + list.emplace_back(dummyPrivate); } return list; } @@ -547,7 +654,7 @@ ChannelList Chat::getChannelList(const std::shared_ptr &player) { std::shared_ptr Chat::getChannel(const std::shared_ptr &player, uint16_t channelId) { switch (channelId) { case CHANNEL_GUILD: { - const auto guild = player->getGuild(); + const auto &guild = player->getGuild(); if (guild != nullptr) { auto it = guildChannels.find(guild->getId()); if (it != guildChannels.end()) { @@ -558,7 +665,7 @@ std::shared_ptr Chat::getChannel(const std::shared_ptr &pla } case CHANNEL_PARTY: { - auto party = player->getParty(); + const auto &party = player->getParty(); if (party != nullptr) { auto it = partyChannels.find(party); if (it != partyChannels.end()) { @@ -578,9 +685,9 @@ std::shared_ptr Chat::getChannel(const std::shared_ptr &pla return channel; } - auto it2 = privateChannels.find(channelId); - if (it2 != privateChannels.end() && it2->second->isInvited(player->getGUID())) { - return it2->second; + auto privateIt = privateChannels.find(channelId); + if (privateIt != privateChannels.end() && privateIt->second->isInvited(player->getGUID())) { + return privateIt->second; } break; } @@ -615,3 +722,7 @@ std::shared_ptr Chat::getPrivateChannel(const std::shared_pt } return nullptr; } + +LuaScriptInterface* Chat::getScriptInterface() { + return &scriptInterface; +} diff --git a/src/creatures/interactions/chat.hpp b/src/creatures/interactions/chat.hpp index fcc74563c34..9dd347aa5b4 100644 --- a/src/creatures/interactions/chat.hpp +++ b/src/creatures/interactions/chat.hpp @@ -9,10 +9,10 @@ #pragma once -#include "utils/utils_definitions.hpp" -#include "lib/di/container.hpp" #include "lua/scripts/luascript.hpp" +enum SpeakClasses : uint8_t; + class Party; class Player; @@ -22,44 +22,30 @@ using InvitedMap = std::map>; class ChatChannel { public: ChatChannel() = default; - ChatChannel(uint16_t channelId, std::string channelName) : - name(std::move(channelName)), - id(channelId) { } + ChatChannel(uint16_t channelId, std::string channelName); virtual ~ChatChannel() = default; bool addUser(const std::shared_ptr &player); bool removeUser(const std::shared_ptr &player); - bool hasUser(const std::shared_ptr &player); + bool hasUser(const std::shared_ptr &player) const; - bool talk(const std::shared_ptr &fromPlayer, SpeakClasses type, const std::string &text); + bool talk(const std::shared_ptr &fromPlayer, SpeakClasses type, const std::string &text) const; void sendToAll(const std::string &message, SpeakClasses type) const; - const std::string &getName() const { - return name; - } - uint16_t getId() const { - return id; - } - const UsersMap &getUsers() const { - return users; - } - virtual const InvitedMap* getInvitedUsers() const { - return nullptr; - } - - virtual uint32_t getOwner() const { - return 0; - } - - bool isPublicChannel() const { - return publicChannel; - } - - bool executeOnJoinEvent(const std::shared_ptr &player); - bool executeCanJoinEvent(const std::shared_ptr &player); - bool executeOnLeaveEvent(const std::shared_ptr &player); - bool executeOnSpeakEvent(const std::shared_ptr &player, SpeakClasses &type, const std::string &message); + const std::string &getName() const; + uint16_t getId() const; + const UsersMap &getUsers() const; + virtual const InvitedMap* getInvitedUsers() const; + + virtual uint32_t getOwner() const; + + bool isPublicChannel() const; + + bool executeOnJoinEvent(const std::shared_ptr &player) const; + bool executeCanJoinEvent(const std::shared_ptr &player) const; + bool executeOnLeaveEvent(const std::shared_ptr &player) const; + bool executeOnSpeakEvent(const std::shared_ptr &player, SpeakClasses &type, const std::string &message) const; protected: UsersMap users; @@ -79,15 +65,10 @@ class ChatChannel { class PrivateChatChannel final : public ChatChannel { public: - PrivateChatChannel(uint16_t channelId, [[maybe_unused]] std::string channelName) : - ChatChannel(channelId, std::move(channelName)) { } + PrivateChatChannel(uint16_t channelId, [[maybe_unused]] std::string channelName); - uint32_t getOwner() const override { - return owner; - } - void setOwner(uint32_t newOwner) { - this->owner = newOwner; - } + uint32_t getOwner() const override; + void setOwner(uint32_t newOwner); bool isInvited(uint32_t guid) const; @@ -98,9 +79,7 @@ class PrivateChatChannel final : public ChatChannel { void closeChannel() const; - [[nodiscard]] const InvitedMap* getInvitedUsers() const override { - return &invites; - } + [[nodiscard]] const InvitedMap* getInvitedUsers() const override; private: InvitedMap invites; @@ -117,9 +96,7 @@ class Chat { Chat(const Chat &) = delete; Chat &operator=(const Chat &) = delete; - static Chat &getInstance() { - return inject(); - } + static Chat &getInstance(); bool load(); @@ -139,9 +116,7 @@ class Chat { std::shared_ptr getGuildChannelById(uint32_t guildId); std::shared_ptr getPrivateChannel(const std::shared_ptr &player) const; - LuaScriptInterface* getScriptInterface() { - return &scriptInterface; - } + LuaScriptInterface* getScriptInterface(); private: std::map> normalChannels; diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 4d225dee696..7276bea19d1 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -8,10 +8,15 @@ */ #include "creatures/monsters/monster.hpp" + +#include "config/configmanager.hpp" #include "creatures/combat/spells.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/players/player.hpp" #include "creatures/players/wheel/player_wheel.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" +#include "items/tile.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" #include "map/spectators.hpp" @@ -22,15 +27,14 @@ int32_t Monster::despawnRadius; uint32_t Monster::monsterAutoID = 0x50000001; std::shared_ptr Monster::createMonster(const std::string &name) { - const auto mType = g_monsters().getMonsterType(name); + const auto &mType = g_monsters().getMonsterType(name); if (!mType) { return nullptr; } return std::make_shared(mType); } -Monster::Monster(const std::shared_ptr mType) : - Creature(), +Monster::Monster(const std::shared_ptr &mType) : nameDescription(asLowerCaseString(mType->nameDescription)), mType(mType) { defaultOutfit = mType->info.outfit; @@ -54,6 +58,20 @@ Monster::Monster(const std::shared_ptr mType) : } } +std::shared_ptr Monster::getMonster() { + return static_self_cast(); +} + +std::shared_ptr Monster::getMonster() const { + return static_self_cast(); +} + +void Monster::setID() { + if (id == 0) { + id = monsterAutoID++; + } +} + void Monster::addList() { g_game().addMonster(static_self_cast()); } @@ -86,6 +104,12 @@ void Monster::setName(const std::string &name) { } } +// Real monster name, set on monster creation "createMonsterType(typeName)" + +const std::string &Monster::getTypeName() const { + return mType->typeName; +} + const std::string &Monster::getNameDescription() const { if (nameDescription.empty()) { return mType->nameDescription; @@ -93,6 +117,26 @@ const std::string &Monster::getNameDescription() const { return nameDescription; } +void Monster::setNameDescription(std::string_view newNameDescription) { + this->nameDescription = newNameDescription; +} + +std::string Monster::getDescription(int32_t) { + return nameDescription + '.'; +} + +CreatureType_t Monster::getType() const { + return CREATURETYPE_MONSTER; +} + +const Position &Monster::getMasterPos() const { + return masterPos; +} + +void Monster::setMasterPos(Position pos) { + masterPos = pos; +} + bool Monster::canWalkOnFieldType(CombatType_t combatType) const { switch (combatType) { case COMBAT_ENERGYDAMAGE: @@ -157,6 +201,69 @@ void Monster::addDefense(int32_t defense) { g_logger().trace("[{}] new defense {}", __FUNCTION__, m_defense); } +Faction_t Monster::getFaction() const { + if (const auto &master = getMaster()) { + return master->getFaction(); + } + return mType->info.faction; +} + +bool Monster::isEnemyFaction(Faction_t faction) const { + const auto &master = getMaster(); + if (master && master->getMonster()) { + return master->getMonster()->isEnemyFaction(faction); + } + return mType->info.enemyFactions.empty() ? false : mType->info.enemyFactions.contains(faction); +} + +bool Monster::isPushable() { + return mType->info.pushable && baseSpeed != 0; +} + +bool Monster::isAttackable() const { + return mType->info.isAttackable; +} + +bool Monster::canPushItems() const { + return mType->info.canPushItems; +} + +bool Monster::canPushCreatures() const { + return mType->info.canPushCreatures; +} + +bool Monster::isRewardBoss() const { + return mType->info.isRewardBoss; +} + +bool Monster::isHostile() const { + return mType->info.isHostile; +} + +bool Monster::isFamiliar() const { + return mType->info.isFamiliar; +} + +bool Monster::canSeeInvisibility() const { + return isImmune(CONDITION_INVISIBLE); +} + +uint16_t Monster::critChance() const { + return mType->info.critChance; +} + +uint32_t Monster::getManaCost() const { + return mType->info.manaCost; +} + +RespawnType Monster::getRespawnType() const { + return mType->info.respawnType; +} + +void Monster::setSpawnMonster(const std::shared_ptr &newSpawnMonster) { + this->spawnMonster = newSpawnMonster; +} + uint32_t Monster::getHealingCombatValue(CombatType_t healingType) const { auto it = mType->info.healingMap.find(healingType); if (it != mType->info.healingMap.end()) { @@ -170,20 +277,20 @@ void Monster::onAttackedCreatureDisappear(bool) { extraMeleeAttack = true; } -void Monster::onCreatureAppear(std::shared_ptr creature, bool isLogin) { +void Monster::onCreatureAppear(const std::shared_ptr &creature, bool isLogin) { Creature::onCreatureAppear(creature, isLogin); if (mType->info.creatureAppearEvent != -1) { // onCreatureAppear(self, creature) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Monster::onCreatureAppear - Monster {} creature {}] " "Call stack overflow. Too many lua script calls being nested.", getName(), creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(mType->info.creatureAppearEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -210,20 +317,20 @@ void Monster::onCreatureAppear(std::shared_ptr creature, bool isLogin) } } -void Monster::onRemoveCreature(std::shared_ptr creature, bool isLogout) { +void Monster::onRemoveCreature(const std::shared_ptr &creature, bool isLogout) { Creature::onRemoveCreature(creature, isLogout); if (mType->info.creatureDisappearEvent != -1) { // onCreatureDisappear(self, creature) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Monster::onCreatureDisappear - Monster {} creature {}] " "Call stack overflow. Too many lua script calls being nested.", getName(), creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(mType->info.creatureDisappearEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -257,14 +364,14 @@ void Monster::onCreatureMove(const std::shared_ptr &creature, const st if (mType->info.creatureMoveEvent != -1) { // onCreatureMove(self, creature, oldPosition, newPosition) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Monster::onCreatureMove - Monster {} creature {}] " "Call stack overflow. Too many lua script calls being nested.", getName(), creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(mType->info.creatureMoveEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -347,20 +454,20 @@ void Monster::onCreatureMove(const std::shared_ptr &creature, const st } } -void Monster::onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) { +void Monster::onCreatureSay(const std::shared_ptr &creature, SpeakClasses type, const std::string &text) { Creature::onCreatureSay(creature, type, text); if (mType->info.creatureSayEvent != -1) { // onCreatureSay(self, creature, type, message) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua " "script calls being nested.", getName(), creature->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(mType->info.creatureSayEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -379,7 +486,7 @@ void Monster::onCreatureSay(std::shared_ptr creature, SpeakClasses typ } } -void Monster::onAttackedByPlayer(std::shared_ptr attackerPlayer) { +void Monster::onAttackedByPlayer(const std::shared_ptr &attackerPlayer) { if (mType->info.monsterAttackedByPlayerEvent != -1) { // onPlayerAttack(self, attackerPlayer) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; @@ -455,7 +562,7 @@ bool Monster::addTarget(const std::shared_ptr &creature, bool pushFron assert(creature != getMonster()); - const auto &it = getTargetIterator(creature); + auto it = getTargetIterator(creature); if (it != targetList.end()) { return false; } @@ -466,7 +573,8 @@ bool Monster::addTarget(const std::shared_ptr &creature, bool pushFron targetList.emplace_back(creature); } - if (!getMaster() && getFaction() != FACTION_DEFAULT && creature->getPlayer()) { + const auto &master = getMaster(); + if (!master && getFaction() != FACTION_DEFAULT && creature->getPlayer()) { totalPlayersOnScreen++; } @@ -478,12 +586,13 @@ bool Monster::removeTarget(const std::shared_ptr &creature) { return false; } - const auto &it = getTargetIterator(creature); + auto it = getTargetIterator(creature); if (it == targetList.end()) { return false; } - if (!getMaster() && getFaction() != FACTION_DEFAULT && creature->getPlayer()) { + const auto &master = getMaster(); + if (!master && getFaction() != FACTION_DEFAULT && creature->getPlayer()) { totalPlayersOnScreen--; } @@ -523,7 +632,7 @@ void Monster::clearFriendList() { friendList.clear(); } -void Monster::onCreatureFound(std::shared_ptr creature, bool pushFront /* = false*/) { +void Monster::onCreatureFound(const std::shared_ptr &creature, bool pushFront /* = false*/) { if (isFriend(creature)) { addFriend(creature); } @@ -535,15 +644,15 @@ void Monster::onCreatureFound(std::shared_ptr creature, bool pushFront updateIdleStatus(); } -void Monster::onCreatureEnter(std::shared_ptr creature) { - onCreatureFound(std::move(creature), true); +void Monster::onCreatureEnter(const std::shared_ptr &creature) { + onCreatureFound(creature, true); } bool Monster::isFriend(const std::shared_ptr &creature) const { - if (isSummon() && getMaster()->getPlayer()) { - const auto &masterPlayer = getMaster()->getPlayer(); + const auto &master = getMaster(); + const auto &masterPlayer = master ? master->getPlayer() : nullptr; + if (isSummon() && masterPlayer) { auto tmpPlayer = creature->getPlayer(); - if (!tmpPlayer) { const auto &creatureMaster = creature->getMaster(); if (creatureMaster && creatureMaster->getPlayer()) { @@ -551,7 +660,7 @@ bool Monster::isFriend(const std::shared_ptr &creature) const { } } - if (tmpPlayer && (tmpPlayer == getMaster() || masterPlayer->isPartner(tmpPlayer))) { + if (tmpPlayer && (tmpPlayer == master || masterPlayer->isPartner(tmpPlayer))) { return true; } } @@ -564,8 +673,10 @@ bool Monster::isOpponent(const std::shared_ptr &creature) const { return false; } - if (isSummon() && getMaster()->getPlayer()) { - return creature != getMaster(); + const auto &master = getMaster(); + const auto &masterPlayer = master ? master->getPlayer() : nullptr; + if (isSummon() && masterPlayer) { + return creature != master; } if (creature->getPlayer() && creature->getPlayer()->hasFlag(PlayerFlags_t::IgnoredByMonsters)) { @@ -576,14 +687,24 @@ bool Monster::isOpponent(const std::shared_ptr &creature) const { return isEnemyFaction(creature->getFaction()) || creature->getFaction() == FACTION_PLAYER; } - if ((creature->getPlayer()) || (creature->getMaster() && creature->getMaster()->getPlayer())) { + const auto &creatureMaster = creature->getMaster(); + const auto &creaturePlayer = creatureMaster ? creatureMaster->getPlayer() : nullptr; + if (creature->getPlayer() || creaturePlayer) { return true; } return false; } -void Monster::onCreatureLeave(std::shared_ptr creature) { +uint64_t Monster::getLostExperience() const { + return skillLoss ? mType->info.experience : 0; +} + +uint16_t Monster::getLookCorpse() const { + return mType->info.lookcorpse; +} + +void Monster::onCreatureLeave(const std::shared_ptr &creature) { // update friendList if (isFriend(creature)) { removeFriend(creature); @@ -626,7 +747,7 @@ bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAUL const auto &creature = cref.lock(); if (creature && isTarget(creature)) { if ((static_self_cast()->targetDistance == 1) || canUseAttack(myPos, creature)) { - resultList.push_back(creature); + resultList.emplace_back(creature); } } } @@ -748,6 +869,10 @@ void Monster::onFollowCreatureComplete(const std::shared_ptr &creature } } +RaceType_t Monster::getRace() const { + return mType->info.race; +} + float Monster::getMitigation() const { float mitigation = mType->info.mitigation * getDefenseMultiplier(); if (g_configManager().getBoolean(DISABLE_MONSTER_ARMOR)) { @@ -756,7 +881,11 @@ float Monster::getMitigation() const { return std::min(mitigation, 30.f); } -BlockType_t Monster::blockHit(std::shared_ptr attacker, CombatType_t combatType, int32_t &damage, bool checkDefense /* = false*/, bool checkArmor /* = false*/, bool /* field = false */) { +int32_t Monster::getArmor() const { + return mType->info.armor * getDefenseMultiplier(); +} + +BlockType_t Monster::blockHit(const std::shared_ptr &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense /* = false*/, bool checkArmor /* = false*/, bool /* field = false */) { BlockType_t blockType = Creature::blockHit(attacker, combatType, damage, checkDefense, checkArmor); if (damage != 0) { @@ -767,7 +896,7 @@ BlockType_t Monster::blockHit(std::shared_ptr attacker, CombatType_t c } // Wheel of destiny - std::shared_ptr player = attacker ? attacker->getPlayer() : nullptr; + const auto &player = attacker ? attacker->getPlayer() : nullptr; if (player && player->wheel()->getInstant("Ballistic Mastery")) { elementMod -= player->wheel()->checkElementSensitiveReduction(combatType); } @@ -784,7 +913,7 @@ BlockType_t Monster::blockHit(std::shared_ptr attacker, CombatType_t c return blockType; } -bool Monster::isTarget(std::shared_ptr creature) { +bool Monster::isTarget(const std::shared_ptr &creature) { if (creature->isRemoved() || !creature->isAttackable() || creature->getZoneType() == ZONE_PROTECTION || !canSeeCreature(creature)) { return false; } @@ -806,12 +935,16 @@ bool Monster::isTarget(std::shared_ptr creature) { return true; } +bool Monster::isFleeing() const { + return !isSummon() && getHealth() <= runAwayHealth && challengeFocusDuration <= 0 && challengeMeleeDuration <= 0; +} + bool Monster::selectTarget(const std::shared_ptr &creature) { if (!isTarget(creature)) { return false; } - const auto &it = getTargetIterator(creature); + auto it = getTargetIterator(creature); if (it == targetList.end()) { // Target not found in our target list. return false; @@ -834,7 +967,6 @@ void Monster::setIdle(bool idle) { if (!isIdle) { g_game().addCreatureCheck(getMonster()); - } else { onIdleStatus(); clearTargetList(); @@ -867,6 +999,10 @@ void Monster::updateIdleStatus() { setIdle(idle); } +bool Monster::getIdleStatus() const { + return isIdle; +} + bool Monster::isInSpawnLocation() const { if (!spawnMonster) { return true; @@ -878,10 +1014,7 @@ void Monster::onAddCondition(ConditionType_t type) { onConditionStatusChange(type); } -void Monster::onConditionStatusChange(const ConditionType_t &type) { - if (type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON) { - updateMapCache(); - } +void Monster::onConditionStatusChange(ConditionType_t /*type*/) { updateIdleStatus(); } @@ -895,14 +1028,14 @@ void Monster::onThink(uint32_t interval) { if (mType->info.thinkEvent != -1) { // onThink(self, interval) LuaScriptInterface* scriptInterface = mType->info.scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("Monster {} Call stack overflow. Too many lua script calls " "being nested.", getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(mType->info.thinkEvent, scriptInterface); lua_State* L = scriptInterface->getLuaState(); @@ -948,17 +1081,18 @@ void Monster::onThink(uint32_t interval) { const auto &attackedCreature = getAttackedCreature(); const auto &followCreature = getFollowCreature(); if (isSummon()) { + const auto &master = getMaster(); if (attackedCreature.get() == this) { setFollowCreature(nullptr); } else if (attackedCreature && followCreature != attackedCreature) { // This happens just after a master orders an attack, so lets follow it aswell. setFollowCreature(attackedCreature); - } else if (getMaster() && getMaster()->getAttackedCreature()) { + } else if (master && master->getAttackedCreature()) { // This happens if the monster is summoned during combat - selectTarget(getMaster()->getAttackedCreature()); - } else if (getMaster() != followCreature) { + selectTarget(master->getAttackedCreature()); + } else if (master && master != followCreature) { // Our master has not ordered us to attack anything, lets follow him around instead. - setFollowCreature(getMaster()); + setFollowCreature(master); } } else if (!targetList.empty()) { const bool attackedCreatureIsDisconnected = attackedCreature && attackedCreature->getPlayer() && attackedCreature->getPlayer()->isDisconnected(); @@ -980,7 +1114,7 @@ void Monster::onThink(uint32_t interval) { } void Monster::doAttacking(uint32_t interval) { - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (!attackedCreature || (isSummon() && attackedCreature.get() == this)) { return; } @@ -1036,6 +1170,10 @@ void Monster::doAttacking(uint32_t interval) { } } +bool Monster::hasExtraSwing() { + return extraMeleeAttack; +} + bool Monster::canUseAttack(const Position &pos, const std::shared_ptr &target) const { if (isHostile()) { const Position &targetPos = target->getPosition(); @@ -1154,8 +1292,8 @@ void Monster::onThinkDefense(uint32_t interval) { } if (!isSummon() && m_summons.size() < mType->info.maxSummons && hasFollowPath) { - for (const summonBlock_t &summonBlock : mType->info.summons) { - if (summonBlock.speed > defenseTicks) { + for (const auto &[summonName, summonChance, summonSpeed, summonCount, summonForce] : mType->info.summons) { + if (summonSpeed > defenseTicks) { resetTicks = false; continue; } @@ -1164,29 +1302,29 @@ void Monster::onThinkDefense(uint32_t interval) { continue; } - if (defenseTicks % summonBlock.speed >= interval) { + if (defenseTicks % summonSpeed >= interval) { // already used this spell for this round continue; } - uint32_t summonCount = 0; + uint32_t summonsCount = 0; for (const auto &summon : m_summons) { - if (summon && summon->getName() == summonBlock.name) { - ++summonCount; + if (summon && summon->getName() == summonName) { + ++summonsCount; } } - if (summonCount >= summonBlock.count) { + if (summonsCount >= summonCount) { continue; } - if (summonBlock.chance < static_cast(uniform_random(1, 100))) { + if (summonChance < static_cast(uniform_random(1, 100))) { continue; } - std::shared_ptr summon = Monster::createMonster(summonBlock.name); + const auto &summon = Monster::createMonster(summonName); if (summon) { - if (g_game().placeCreature(summon, getPosition(), false, summonBlock.force)) { + if (g_game().placeCreature(summon, getPosition(), false, summonForce)) { summon->setMaster(static_self_cast(), true); g_game().addMagicEffect(getPosition(), CONST_ME_MAGIC_BLUE); g_game().addMagicEffect(summon->getPosition(), CONST_ME_TELEPORT); @@ -1211,13 +1349,13 @@ void Monster::onThinkYell(uint32_t interval) { yellTicks = 0; if (!mType->info.voiceVector.empty() && (mType->info.yellChance >= static_cast(uniform_random(1, 100)))) { - uint32_t index = uniform_random(0, mType->info.voiceVector.size() - 1); - const voiceBlock_t &vb = mType->info.voiceVector[index]; + const uint32_t index = uniform_random(0, mType->info.voiceVector.size() - 1); + const auto &[text, yellText] = mType->info.voiceVector[index]; - if (vb.yellText) { - g_game().internalCreatureSay(static_self_cast(), TALKTYPE_MONSTER_YELL, vb.text, false); + if (yellText) { + g_game().internalCreatureSay(static_self_cast(), TALKTYPE_MONSTER_YELL, text, false); } else { - g_game().internalCreatureSay(static_self_cast(), TALKTYPE_MONSTER_SAY, vb.text, false); + g_game().internalCreatureSay(static_self_cast(), TALKTYPE_MONSTER_SAY, text, false); } } } @@ -1239,7 +1377,7 @@ void Monster::onThinkSound(uint32_t interval) { } } -bool Monster::pushItem(std::shared_ptr item, const Direction &nextDirection) { +bool Monster::pushItem(const std::shared_ptr &item, const Direction &nextDirection) { const Position ¢erPos = item->getPosition(); for (const auto &[x, y] : getPushItemLocationOptions(nextDirection)) { Position tryPos(centerPos.x + x, centerPos.y + y, centerPos.z); @@ -1251,11 +1389,11 @@ bool Monster::pushItem(std::shared_ptr item, const Direction &nextDirectio return false; } -void Monster::pushItems(std::shared_ptr tile, const Direction &nextDirection) { +void Monster::pushItems(const std::shared_ptr &tile, const Direction &nextDirection) { // We can not use iterators here since we can push the item to another tile // which will invalidate the iterator. // start from the end to minimize the amount of traffic - if (const auto items = tile->getItemList()) { + if (const auto &items = tile->getItemList()) { uint32_t moveCount = 0; uint32_t removeCount = 0; int32_t downItemSize = tile->getDownItemCount(); @@ -1275,17 +1413,17 @@ void Monster::pushItems(std::shared_ptr tile, const Direction &nextDirecti } } -bool Monster::pushCreature(std::shared_ptr creature) { +bool Monster::pushCreature(const std::shared_ptr &creature) { static std::vector dirList { DIRECTION_NORTH, DIRECTION_WEST, DIRECTION_EAST, DIRECTION_SOUTH }; - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); + std::ranges::shuffle(dirList, getRandomGenerator()); - for (Direction dir : dirList) { + for (const Direction &dir : dirList) { const Position &tryPos = Spells::getCasterPosition(creature, dir); - const auto toTile = g_game().map.getTile(tryPos); + const auto &toTile = g_game().map.getTile(tryPos); if (toTile && !toTile->hasFlag(TILESTATE_BLOCKPATH) && g_game().internalMoveCreature(creature, dir) == RETURNVALUE_NOERROR) { return true; } @@ -1293,15 +1431,15 @@ bool Monster::pushCreature(std::shared_ptr creature) { return false; } -void Monster::pushCreatures(std::shared_ptr tile) { +void Monster::pushCreatures(const std::shared_ptr &tile) { // We can not use iterators here since we can push a creature to another tile // which will invalidate the iterator. - if (CreatureVector* creatures = tile->getCreatures()) { + if (const CreatureVector* creatures = tile->getCreatures()) { uint32_t removeCount = 0; std::shared_ptr lastPushedMonster = nullptr; for (size_t i = 0; i < creatures->size();) { - std::shared_ptr monster = creatures->at(i)->getMonster(); + const auto &monster = creatures->at(i)->getMonster(); if (monster && monster->isPushable()) { if (monster != lastPushedMonster && Monster::pushCreature(monster)) { lastPushedMonster = monster; @@ -1341,7 +1479,7 @@ bool Monster::getNextStep(Direction &nextDirection, uint32_t &flags) { if (result && (canPushItems() || canPushCreatures())) { const Position &pos = getNextPosition(nextDirection, getPosition()); - auto posTile = g_game().map.getTile(pos); + const auto &posTile = g_game().map.getTile(pos); if (posTile) { if (canPushItems()) { Monster::pushItems(posTile, nextDirection); @@ -1376,7 +1514,6 @@ void Monster::doWalkBack(uint32_t &flags, Direction &nextDirection, bool &result } else { if (ignoreFieldDamage) { ignoreFieldDamage = false; - updateMapCache(); } int32_t distance = std::max(Position::getDistanceX(position, masterPos), Position::getDistanceY(position, masterPos)); @@ -1402,11 +1539,10 @@ void Monster::doFollowCreature(uint32_t &flags, Direction &nextDirection, bool & } else { if (ignoreFieldDamage) { ignoreFieldDamage = false; - updateMapCache(); } // target dancing - auto attackedCreature = getAttackedCreature(); - auto followCreature = getFollowCreature(); + const auto &attackedCreature = getAttackedCreature(); + const auto &followCreature = getFollowCreature(); if (attackedCreature && attackedCreature == followCreature) { if (isFleeing()) { result = getDanceStep(getPosition(), nextDirection, false, false); @@ -1423,9 +1559,9 @@ bool Monster::getRandomStep(const Position &creaturePos, Direction &moveDirectio DIRECTION_WEST, DIRECTION_EAST, DIRECTION_SOUTH }; - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); + std::ranges::shuffle(dirList, getRandomGenerator()); - for (Direction dir : dirList) { + for (const Direction &dir : dirList) { if (canWalkTo(creaturePos, dir)) { moveDirection = dir; return true; @@ -1435,7 +1571,7 @@ bool Monster::getRandomStep(const Position &creaturePos, Direction &moveDirectio } bool Monster::getDanceStep(const Position &creaturePos, Direction &moveDirection, bool keepAttack /*= true*/, bool keepDistance /*= true*/) { - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (!attackedCreature) { return false; } @@ -2016,14 +2152,75 @@ bool Monster::getDistanceStep(const Position &targetPos, Direction &moveDirectio return true; } +bool Monster::isTargetNearby() const { + return stepDuration >= 1; +} + +bool Monster::isIgnoringFieldDamage() const { + return ignoreFieldDamage; +} + +bool Monster::israndomStepping() const { + return randomStepping; +} + +void Monster::setIgnoreFieldDamage(bool ignore) { + ignoreFieldDamage = ignore; +} + +bool Monster::getIgnoreFieldDamage() const { + return ignoreFieldDamage; +} + +uint16_t Monster::getRaceId() const { + return mType->info.raceid; +} + +// Hazard system +bool Monster::getHazard() const { + return hazard; +} + +void Monster::setHazard(bool value) { + hazard = value; +} + +bool Monster::getHazardSystemCrit() const { + return hazardCrit; +} + +void Monster::setHazardSystemCrit(bool value) { + hazardCrit = value; +} + +bool Monster::getHazardSystemDodge() const { + return hazardDodge; +} + +void Monster::setHazardSystemDodge(bool value) { + hazardDodge = value; +} + +bool Monster::getHazardSystemDamageBoost() const { + return hazardDamageBoost; +} + +void Monster::setHazardSystemDamageBoost(bool value) { + hazardDamageBoost = value; +} + +bool Monster::getHazardSystemDefenseBoost() const { + return hazardDefenseBoost; +} + +void Monster::setHazardSystemDefenseBoost(bool value) { + hazardDefenseBoost = value; +} + bool Monster::canWalkTo(Position pos, Direction moveDirection) { pos = getNextPosition(moveDirection, pos); if (isInSpawnRange(pos)) { - if (getWalkCache(pos) == 0) { - return false; - } - - const auto tile = g_game().map.getTile(pos); + const auto &tile = g_game().map.getTile(pos); if (tile && tile->getTopVisibleCreature(getMonster()) == nullptr && tile->queryAdd(0, getMonster(), 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RETURNVALUE_NOERROR) { return true; } @@ -2031,7 +2228,7 @@ bool Monster::canWalkTo(Position pos, Direction moveDirection) { return false; } -void Monster::death(std::shared_ptr) { +void Monster::death(const std::shared_ptr &) { if (monsterForgeClassification > ForgeClassifications_t::FORGE_NORMAL_MONSTER) { g_game().removeForgeMonster(getID(), monsterForgeClassification, true); } @@ -2057,14 +2254,14 @@ void Monster::death(std::shared_ptr) { setDead(true); } -std::shared_ptr Monster::getCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature) { - std::shared_ptr corpse = Creature::getCorpse(lastHitCreature, mostDamageCreature); +std::shared_ptr Monster::getCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature) { + const auto &corpse = Creature::getCorpse(lastHitCreature, mostDamageCreature); if (corpse) { if (mostDamageCreature) { if (mostDamageCreature->getPlayer()) { corpse->setAttribute(ItemAttribute_t::CORPSEOWNER, mostDamageCreature->getID()); } else { - std::shared_ptr mostDamageCreatureMaster = mostDamageCreature->getMaster(); + const auto &mostDamageCreatureMaster = mostDamageCreature->getMaster(); if (mostDamageCreatureMaster && mostDamageCreatureMaster->getPlayer()) { corpse->setAttribute(ItemAttribute_t::CORPSEOWNER, mostDamageCreatureMaster->getID()); } @@ -2110,7 +2307,7 @@ bool Monster::getCombatValues(int32_t &min, int32_t &max) { void Monster::updateLookDirection() { Direction newDir = getDirection(); - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (!attackedCreature) { return; } @@ -2167,7 +2364,7 @@ void Monster::updateLookDirection() { g_game().internalCreatureTurn(getMonster(), newDir); } -void Monster::dropLoot(std::shared_ptr corpse, std::shared_ptr) { +void Monster::dropLoot(const std::shared_ptr &corpse, const std::shared_ptr &) { if (corpse && lootDrop) { // Only fiendish drops sliver if (ForgeClassifications_t classification = getMonsterForgeClassification(); @@ -2178,7 +2375,7 @@ void Monster::dropLoot(std::shared_ptr corpse, std::shared_ptr(uniform_random(minSlivers, maxSlivers)); - std::shared_ptr sliver = Item::CreateItem(ITEM_FORGE_SLIVER, sliverCount); + const auto &sliver = Item::CreateItem(ITEM_FORGE_SLIVER, sliverCount); if (g_game().internalAddItem(corpse, sliver) != RETURNVALUE_NOERROR) { corpse->internalAddThing(sliver); } @@ -2194,12 +2391,11 @@ void Monster::setNormalCreatureLight() { internalLight = mType->info.light; } -void Monster::drainHealth(std::shared_ptr attacker, int32_t damage) { +void Monster::drainHealth(const std::shared_ptr &attacker, int32_t damage) { Creature::drainHealth(attacker, damage); if (damage > 0 && randomStepping) { ignoreFieldDamage = true; - updateMapCache(); } if (isInvisible()) { @@ -2218,7 +2414,7 @@ void Monster::changeHealth(int32_t healthChange, bool sendHealthChange /* = true Creature::changeHealth(healthChange, sendHealthChange); } -bool Monster::challengeCreature(std::shared_ptr creature, int targetChangeCooldown) { +bool Monster::challengeCreature(const std::shared_ptr &creature, int targetChangeCooldown) { if (isSummon()) { return false; } @@ -2228,7 +2424,7 @@ bool Monster::challengeCreature(std::shared_ptr creature, int targetCh challengeFocusDuration = targetChangeCooldown; targetChangeTicks = 0; // Wheel of destiny - std::shared_ptr player = creature ? creature->getPlayer() : nullptr; + const auto &player = creature ? creature->getPlayer() : nullptr; if (player && !player->isRemoved()) { player->wheel()->healIfBattleHealingActive(); } @@ -2255,6 +2451,27 @@ bool Monster::changeTargetDistance(int32_t distance, uint32_t duration /* = 1200 return true; } +bool Monster::isChallenged() const { + return challengeFocusDuration > 0; +} + +std::vector Monster::getIcons() const { + auto creatureIcons = Creature::getIcons(); + if (!creatureIcons.empty()) { + return creatureIcons; + } + + using enum CreatureIconModifications_t; + if (challengeMeleeDuration > 0 && mType->info.targetDistance > targetDistance) { + return { CreatureIcon(TurnedMelee) }; + } else if (varBuffs[BUFF_DAMAGERECEIVED] > 100) { + return { CreatureIcon(HigherDamageReceived) }; + } else if (varBuffs[BUFF_DAMAGEDEALT] < 100) { + return { CreatureIcon(LowerDamageDealt) }; + } + return {}; +} + bool Monster::isImmune(ConditionType_t conditionType) const { return m_isImmune || mType->info.m_conditionImmunities[static_cast(conditionType)]; } @@ -2263,6 +2480,38 @@ bool Monster::isImmune(CombatType_t combatType) const { return m_isImmune || mType->info.m_damageImmunities[combatTypeToIndex(combatType)]; } +void Monster::setImmune(bool immune) { + m_isImmune = immune; +} + +bool Monster::isImmune() const { + return m_isImmune; +} + +float Monster::getAttackMultiplier() const { + float multiplier = mType->getAttackMultiplier(); + if (auto stacks = getForgeStack(); stacks > 0) { + multiplier *= (1.35 + (stacks - 1) * 0.1); + } + return multiplier; +} + +float Monster::getDefenseMultiplier() const { + float multiplier = mType->getDefenseMultiplier(); + if (auto stacks = getForgeStack(); stacks > 0) { + multiplier *= (1 + (0.1 * stacks)); + } + return multiplier; +} + +bool Monster::isDead() const { + return m_isDead; +} + +void Monster::setDead(bool isDead) { + m_isDead = isDead; +} + void Monster::getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) { Creature::getPathSearchParams(creature, fpp); @@ -2270,7 +2519,8 @@ void Monster::getPathSearchParams(const std::shared_ptr &creature, Fin fpp.maxTargetDist = targetDistance; if (isSummon()) { - if (getMaster() == creature) { + const auto &master = getMaster(); + if (master && master == creature) { fpp.maxTargetDist = 2; fpp.fullPathSearch = true; } else if (targetDistance <= 1) { @@ -2321,6 +2571,46 @@ void Monster::configureForgeSystem() { g_game().sendUpdateCreature(static_self_cast()); } +bool Monster::canBeForgeMonster() const { + return getForgeStack() == 0 && !isSummon() && !isRewardBoss() && canDropLoot() && isForgeCreature() && getRaceId() > 0; +} + +bool Monster::isForgeCreature() const { + return mType->info.isForgeCreature; +} + +void Monster::setForgeMonster(bool forge) const { + mType->info.isForgeCreature = forge; +} + +uint16_t Monster::getForgeStack() const { + return forgeStack; +} + +void Monster::setForgeStack(uint16_t stack) { + forgeStack = stack; +} + +ForgeClassifications_t Monster::getMonsterForgeClassification() const { + return monsterForgeClassification; +} + +void Monster::setMonsterForgeClassification(ForgeClassifications_t classification) { + monsterForgeClassification = classification; +} + +void Monster::setTimeToChangeFiendish(time_t time) { + timeToChangeFiendish = time; +} + +time_t Monster::getTimeToChangeFiendish() const { + return timeToChangeFiendish; +} + +std::shared_ptr Monster::getMonsterType() const { + return mType; +} + void Monster::clearFiendishStatus() { timeToChangeFiendish = 0; forgeStack = 0; diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index 36562af1e0f..b8a6087acc1 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -8,13 +8,17 @@ */ #pragma once +#include "creatures/creature.hpp" +#include "lua/lua_definitions.hpp" -#include "creatures/monsters/monsters.hpp" -#include "declarations.hpp" -#include "items/tile.hpp" - +struct spellBlock_t; +class MonsterType; +class Tile; class Creature; class Game; +class SpawnMonster; + +using CreatureVector = std::vector>; class Monster final : public Creature { public: @@ -22,24 +26,16 @@ class Monster final : public Creature { static int32_t despawnRange; static int32_t despawnRadius; - explicit Monster(std::shared_ptr mType); + explicit Monster(const std::shared_ptr &mType); // non-copyable Monster(const Monster &) = delete; Monster &operator=(const Monster &) = delete; - std::shared_ptr getMonster() override { - return static_self_cast(); - } - std::shared_ptr getMonster() const override { - return static_self_cast(); - } + std::shared_ptr getMonster() override; + std::shared_ptr getMonster() const override; - void setID() override { - if (id == 0) { - id = monsterAutoID++; - } - } + void setID() override; void addList() override; void removeList() override; @@ -48,91 +44,39 @@ class Monster final : public Creature { void setName(const std::string &name); // Real monster name, set on monster creation "createMonsterType(typeName)" - const std::string &getTypeName() const override { - return mType->typeName; - } + const std::string &getTypeName() const override; const std::string &getNameDescription() const override; - void setNameDescription(const std::string &nameDescription) { - this->nameDescription = nameDescription; - }; - std::string getDescription(int32_t) override { - return nameDescription + '.'; - } + void setNameDescription(std::string_view nameDescription); + std::string getDescription(int32_t) override; - CreatureType_t getType() const override { - return CREATURETYPE_MONSTER; - } + CreatureType_t getType() const override; - const Position &getMasterPos() const { - return masterPos; - } - void setMasterPos(Position pos) { - masterPos = pos; - } + const Position &getMasterPos() const; + void setMasterPos(Position pos); - RaceType_t getRace() const override { - return mType->info.race; - } + RaceType_t getRace() const override; float getMitigation() const override; - int32_t getArmor() const override { - return mType->info.armor * getDefenseMultiplier(); - } + int32_t getArmor() const override; int32_t getDefense() const override; void addDefense(int32_t defense); - Faction_t getFaction() const override { - auto master = getMaster(); - if (getMaster()) { - return getMaster()->getFaction(); - } - return mType->info.faction; - } + Faction_t getFaction() const override; - bool isEnemyFaction(Faction_t faction) const { - auto master = getMaster(); - if (master && master->getMonster()) { - return master->getMonster()->isEnemyFaction(faction); - } - return mType->info.enemyFactions.empty() ? false : mType->info.enemyFactions.contains(faction); - } + bool isEnemyFaction(Faction_t faction) const; - bool isPushable() override { - return mType->info.pushable && baseSpeed != 0; - } - bool isAttackable() const override { - return mType->info.isAttackable; - } - bool canPushItems() const { - return mType->info.canPushItems; - } - bool canPushCreatures() const { - return mType->info.canPushCreatures; - } - bool isRewardBoss() const { - return mType->info.isRewardBoss; - } - bool isHostile() const { - return mType->info.isHostile; - } - bool isFamiliar() const { - return mType->info.isFamiliar; - } - bool canSeeInvisibility() const override { - return isImmune(CONDITION_INVISIBLE); - } - uint16_t critChance() const { - return mType->info.critChance; - } - uint32_t getManaCost() const { - return mType->info.manaCost; - } - RespawnType getRespawnType() const { - return mType->info.respawnType; - } - void setSpawnMonster(SpawnMonster* newSpawnMonster) { - this->spawnMonster = newSpawnMonster; - } + bool isPushable() override; + bool isAttackable() const override; + bool canPushItems() const; + bool canPushCreatures() const; + bool isRewardBoss() const; + bool isHostile() const; + bool isFamiliar() const; + bool canSeeInvisibility() const override; + uint16_t critChance() const; + uint32_t getManaCost() const; + RespawnType getRespawnType() const; + void setSpawnMonster(const std::shared_ptr &newSpawnMonster); double_t getReflectPercent(CombatType_t combatType, bool useCharges = false) const override; uint32_t getHealingCombatValue(CombatType_t healingType) const; @@ -142,49 +86,32 @@ class Monster final : public Creature { bool canWalkOnFieldType(CombatType_t combatType) const; void onAttackedCreatureDisappear(bool isLogout) override; - void onCreatureAppear(std::shared_ptr creature, bool isLogin) override; - void onRemoveCreature(std::shared_ptr creature, bool isLogout) override; + void onCreatureAppear(const std::shared_ptr &creature, bool isLogin) override; + void onRemoveCreature(const std::shared_ptr &creature, bool isLogout) override; void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) override; - void onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) override; - void onAttackedByPlayer(std::shared_ptr attackerPlayer); + void onCreatureSay(const std::shared_ptr &creature, SpeakClasses type, const std::string &text) override; + void onAttackedByPlayer(const std::shared_ptr &attackerPlayer); void onSpawn(); - void drainHealth(std::shared_ptr attacker, int32_t damage) override; + void drainHealth(const std::shared_ptr &attacker, int32_t damage) override; void changeHealth(int32_t healthChange, bool sendHealthChange = true) override; bool getNextStep(Direction &direction, uint32_t &flags) override; void onFollowCreatureComplete(const std::shared_ptr &creature) override; void onThink(uint32_t interval) override; - bool challengeCreature(std::shared_ptr creature, int targetChangeCooldown) override; + bool challengeCreature(const std::shared_ptr &creature, int targetChangeCooldown) override; bool changeTargetDistance(int32_t distance, uint32_t duration = 12000); - bool isChallenged() const { - return challengeFocusDuration > 0; - } + bool isChallenged() const; - std::vector getIcons() const override { - auto creatureIcons = Creature::getIcons(); - if (!creatureIcons.empty()) { - return creatureIcons; - } - if (challengeMeleeDuration > 0 && mType->info.targetDistance > targetDistance) { - return { CreatureIcon(CreatureIconModifications_t::TurnedMelee) }; - } else if (varBuffs[BUFF_DAMAGERECEIVED] > 100) { - return { CreatureIcon(CreatureIconModifications_t::HigherDamageReceived) }; - } else if (varBuffs[BUFF_DAMAGEDEALT] < 100) { - return { CreatureIcon(CreatureIconModifications_t::LowerDamageDealt) }; - } - return {}; - } + std::vector getIcons() const override; void setNormalCreatureLight() override; bool getCombatValues(int32_t &min, int32_t &max) override; void doAttacking(uint32_t interval) override; - bool hasExtraSwing() override { - return extraMeleeAttack; - } + bool hasExtraSwing() override; bool searchTarget(TargetSearchType_t searchType = TARGETSEARCH_DEFAULT); bool selectTarget(const std::shared_ptr &creature); @@ -221,152 +148,78 @@ class Monster final : public Creature { return list; } - bool isTarget(std::shared_ptr creature); - bool isFleeing() const { - return !isSummon() && getHealth() <= runAwayHealth && challengeFocusDuration <= 0 && challengeMeleeDuration <= 0; - } + bool isTarget(const std::shared_ptr &creature); + bool isFleeing() const; bool getDistanceStep(const Position &targetPos, Direction &direction, bool flee = false); - bool isTargetNearby() const { - return stepDuration >= 1; - } - bool isIgnoringFieldDamage() const { - return ignoreFieldDamage; - } - bool israndomStepping() const { - return randomStepping; - } - void setIgnoreFieldDamage(bool ignore) { - ignoreFieldDamage = ignore; - } - bool getIgnoreFieldDamage() const { - return ignoreFieldDamage; - } - uint16_t getRaceId() const { - return mType->info.raceid; - } + bool isTargetNearby() const; + bool isIgnoringFieldDamage() const; + bool israndomStepping() const; + void setIgnoreFieldDamage(bool ignore); + bool getIgnoreFieldDamage() const; + uint16_t getRaceId() const; // Hazard system - bool getHazard() const { - return hazard; - } - void setHazard(bool value) { - hazard = value; - } + bool getHazard() const; + void setHazard(bool value); - bool getHazardSystemCrit() const { - return hazardCrit; - } - void setHazardSystemCrit(bool value) { - hazardCrit = value; - } + bool getHazardSystemCrit() const; + void setHazardSystemCrit(bool value); - bool getHazardSystemDodge() const { - return hazardDodge; - } - void setHazardSystemDodge(bool value) { - hazardDodge = value; - } + bool getHazardSystemDodge() const; + void setHazardSystemDodge(bool value); - bool getHazardSystemDamageBoost() const { - return hazardDamageBoost; - } - void setHazardSystemDamageBoost(bool value) { - hazardDamageBoost = value; - } - bool getHazardSystemDefenseBoost() const { - return hazardDefenseBoost; - } - void setHazardSystemDefenseBoost(bool value) { - hazardDefenseBoost = value; - } + bool getHazardSystemDamageBoost() const; + void setHazardSystemDamageBoost(bool value); + bool getHazardSystemDefenseBoost() const; + void setHazardSystemDefenseBoost(bool value); // Hazard end void updateTargetList(); void clearTargetList(); void clearFriendList(); - BlockType_t blockHit(std::shared_ptr attacker, CombatType_t combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false) override; + BlockType_t blockHit(const std::shared_ptr &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false) override; static uint32_t monsterAutoID; void configureForgeSystem(); - bool canBeForgeMonster() const { - return getForgeStack() == 0 && !isSummon() && !isRewardBoss() && canDropLoot() && isForgeCreature() && getRaceId() > 0; - } + bool canBeForgeMonster() const; - bool isForgeCreature() const { - return mType->info.isForgeCreature; - } + bool isForgeCreature() const; - void setForgeMonster(bool forge) const { - mType->info.isForgeCreature = forge; - } + void setForgeMonster(bool forge) const; - uint16_t getForgeStack() const { - return forgeStack; - } + uint16_t getForgeStack() const; - void setForgeStack(uint16_t stack) { - forgeStack = stack; - } + void setForgeStack(uint16_t stack); - ForgeClassifications_t getMonsterForgeClassification() const { - return monsterForgeClassification; - } + ForgeClassifications_t getMonsterForgeClassification() const; - void setMonsterForgeClassification(ForgeClassifications_t classification) { - monsterForgeClassification = classification; - } + void setMonsterForgeClassification(ForgeClassifications_t classification); - void setTimeToChangeFiendish(time_t time) { - timeToChangeFiendish = time; - } + void setTimeToChangeFiendish(time_t time); - time_t getTimeToChangeFiendish() const { - return timeToChangeFiendish; - } + time_t getTimeToChangeFiendish() const; - std::shared_ptr getMonsterType() const { - return mType; - } + std::shared_ptr getMonsterType() const; void clearFiendishStatus(); bool canDropLoot() const; bool isImmune(ConditionType_t conditionType) const override; bool isImmune(CombatType_t combatType) const override; - void setImmune(bool immune) { - m_isImmune = immune; - } - bool isImmune() const { - return m_isImmune; - } + void setImmune(bool immune); + bool isImmune() const; - float getAttackMultiplier() const { - float multiplier = mType->getAttackMultiplier(); - if (auto stacks = getForgeStack(); stacks > 0) { - multiplier *= (1.35 + (stacks - 1) * 0.1); - } - return multiplier; - } + float getAttackMultiplier() const; - float getDefenseMultiplier() const { - float multiplier = mType->getDefenseMultiplier(); - if (auto stacks = getForgeStack(); stacks > 0) { - multiplier *= (1 + (0.1 * stacks)); - } - return multiplier; - } + float getDefenseMultiplier() const; - bool isDead() const override { - return m_isDead; - } + bool isDead() const override; - void setDead(bool isDead) { - m_isDead = isDead; - } + void setDead(bool isDead); protected: void onExecuteAsyncTasks() override; @@ -392,7 +245,7 @@ class Monster final : public Creature { std::string nameDescription; std::shared_ptr mType; - SpawnMonster* spawnMonster = nullptr; + std::shared_ptr spawnMonster = nullptr; int64_t lastMeleeAttack = 0; @@ -433,9 +286,9 @@ class Monster final : public Creature { bool m_isDead = false; bool m_isImmune = false; - void onCreatureEnter(std::shared_ptr creature); - void onCreatureLeave(std::shared_ptr creature); - void onCreatureFound(std::shared_ptr creature, bool pushFront = false); + void onCreatureEnter(const std::shared_ptr &creature); + void onCreatureLeave(const std::shared_ptr &creature); + void onCreatureFound(const std::shared_ptr &creature, bool pushFront = false); void updateLookDirection(); @@ -444,14 +297,12 @@ class Monster final : public Creature { bool addTarget(const std::shared_ptr &creature, bool pushFront = false); bool removeTarget(const std::shared_ptr &creature); - void death(std::shared_ptr lastHitCreature) override; - std::shared_ptr getCorpse(std::shared_ptr lastHitCreature, std::shared_ptr mostDamageCreature) override; + void death(const std::shared_ptr &lastHitCreature) override; + std::shared_ptr getCorpse(const std::shared_ptr &lastHitCreature, const std::shared_ptr &mostDamageCreature) override; void setIdle(bool idle); void updateIdleStatus(); - bool getIdleStatus() const { - return isIdle; - } + bool getIdleStatus() const; void onAddCondition(ConditionType_t type) override; void onEndCondition(ConditionType_t type) override; @@ -464,10 +315,10 @@ class Monster final : public Creature { bool isInSpawnRange(const Position &pos) const; bool canWalkTo(Position pos, Direction direction); - static bool pushItem(std::shared_ptr item, const Direction &nextDirection); - static void pushItems(std::shared_ptr tile, const Direction &nextDirection); - static bool pushCreature(std::shared_ptr creature); - static void pushCreatures(std::shared_ptr tile); + static bool pushItem(const std::shared_ptr &item, const Direction &nextDirection); + static void pushItems(const std::shared_ptr &tile, const Direction &nextDirection); + static bool pushCreature(const std::shared_ptr &creature); + static void pushCreatures(const std::shared_ptr &tile); void onThinkTarget(uint32_t interval); void onThinkYell(uint32_t interval); @@ -477,21 +328,10 @@ class Monster final : public Creature { bool isFriend(const std::shared_ptr &creature) const; bool isOpponent(const std::shared_ptr &creature) const; - uint64_t getLostExperience() const override { - return skillLoss ? mType->info.experience : 0; - } - uint16_t getLookCorpse() const override { - return mType->info.lookcorpse; - } - void dropLoot(std::shared_ptr corpse, std::shared_ptr lastHitCreature) override; + uint64_t getLostExperience() const override; + uint16_t getLookCorpse() const override; + void dropLoot(const std::shared_ptr &corpse, const std::shared_ptr &lastHitCreature) override; void getPathSearchParams(const std::shared_ptr &creature, FindPathParams &fpp) override; - bool useCacheMap() const override { - // return !randomStepping; - // As the map cache is done synchronously for each movement that a monster makes, it is better to disable it, - // as the pathfinder, which is one of the resources that uses this cache the most, - // is multithreding and thus the processing cost is divided between the threads. - return false; - } friend class MonsterFunctions; friend class Map; @@ -502,5 +342,5 @@ class Monster final : public Creature { void doFollowCreature(uint32_t &flags, Direction &nextDirection, bool &result); void doRandomStep(Direction &nextDirection, bool &result); - void onConditionStatusChange(const ConditionType_t &type); + void onConditionStatusChange(ConditionType_t type); }; diff --git a/src/creatures/monsters/monsters.cpp b/src/creatures/monsters/monsters.cpp index 9a1c2b70634..cd33e12e248 100644 --- a/src/creatures/monsters/monsters.cpp +++ b/src/creatures/monsters/monsters.cpp @@ -9,28 +9,32 @@ #include "creatures/monsters/monsters.hpp" -#include "creatures/combat/spells.hpp" +#include "config/configmanager.hpp" #include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/combat/spells.hpp" #include "game/game.hpp" #include "items/weapons/weapons.hpp" +#include "lua/scripts/luascript.hpp" +#include "lib/di/container.hpp" -void MonsterType::loadLoot(const std::shared_ptr monsterType, LootBlock lootBlock) { +void MonsterType::loadLoot(const std::shared_ptr &monsterType, LootBlock lootBlock) const { if (lootBlock.childLoot.empty()) { - bool isContainer = Item::items[lootBlock.id].isContainer(); + const bool isContainer = Item::items[lootBlock.id].isContainer(); if (isContainer) { for (const LootBlock &child : lootBlock.childLoot) { - lootBlock.childLoot.push_back(child); + lootBlock.childLoot.emplace_back(child); } } - monsterType->info.lootItems.push_back(lootBlock); + monsterType->info.lootItems.emplace_back(lootBlock); } else { - monsterType->info.lootItems.push_back(lootBlock); + monsterType->info.lootItems.emplace_back(lootBlock); } } -bool MonsterType::canSpawn(const Position &pos) { +bool MonsterType::canSpawn(const Position &pos) const { bool canSpawn = true; - bool isDay = g_game().gameIsDay(); + const bool isDay = g_game().gameIsDay(); if ((isDay && info.respawnType.period == RESPAWNPERIOD_NIGHT) || (!isDay && info.respawnType.period == RESPAWNPERIOD_DAY)) { // It will ignore day and night if underground @@ -40,8 +44,8 @@ bool MonsterType::canSpawn(const Position &pos) { return canSpawn; } -std::shared_ptr Monsters::getDamageCondition(ConditionType_t conditionType, int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval) { - std::shared_ptr condition = Condition::createCondition(CONDITIONID_COMBAT, conditionType, 0, 0)->static_self_cast(); +std::shared_ptr Monsters::getDamageCondition(ConditionType_t conditionType, int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval) const { + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, conditionType, 0, 0)->static_self_cast(); condition->setParam(CONDITION_PARAM_TICKINTERVAL, tickInterval); condition->setParam(CONDITION_PARAM_MINVALUE, minDamage); condition->setParam(CONDITION_PARAM_MAXVALUE, maxDamage); @@ -50,7 +54,7 @@ std::shared_ptr Monsters::getDamageCondition(ConditionType_t co return condition; } -bool Monsters::deserializeSpell(const std::shared_ptr spell, spellBlock_t &sb, const std::string &description) { +bool Monsters::deserializeSpell(const std::shared_ptr &spell, spellBlock_t &sb, const std::string &description) const { if (!spell->scriptName.empty()) { spell->isScripted = true; } else if (!spell->name.empty()) { @@ -60,8 +64,8 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell } sb.speed = spell->interval; - sb.chance = std::min((int)spell->chance, 100); - sb.range = std::min((int)spell->range, MAP_MAX_VIEW_PORT_X * 2); + sb.chance = std::min(static_cast(spell->chance), 100); + sb.range = std::min(static_cast(spell->range), MAP_MAX_VIEW_PORT_X * 2); sb.minCombatValue = std::min(spell->minCombatValue, spell->maxCombatValue); sb.maxCombatValue = std::max(spell->minCombatValue, spell->maxCombatValue); sb.soundCastEffect = spell->soundCastEffect; @@ -94,7 +98,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell combatPtr->setArea(area); } - if (std::string spellName = asLowerCaseString(spell->name); + if (const std::string spellName = asLowerCaseString(spell->name); spellName == "melee") { sb.isMelee = true; @@ -141,8 +145,8 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell conditionType = CONDITION_PARALYZE; } - std::shared_ptr condition = Condition::createCondition(CONDITIONID_COMBAT, conditionType, duration, 0)->static_self_cast(); - float multiplier = 1.0f + static_cast(speedChange) / 1000.0f; + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, conditionType, duration, 0)->static_self_cast(); + const float multiplier = 1.0f + static_cast(speedChange) / 1000.0f; condition->setFormulaVars(multiplier / 2, 40, multiplier, 40); combatPtr->addCondition(condition); } else if (spellName == "outfit") { @@ -152,7 +156,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell duration = spell->duration; } - std::shared_ptr condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)->static_self_cast(); + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)->static_self_cast(); if (!spell->outfitMonster.empty()) { condition->setLazyMonsterOutfit(spell->outfitMonster); @@ -176,7 +180,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell duration = spell->duration; } - std::shared_ptr condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_INVISIBLE, duration, 0); + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_INVISIBLE, duration, 0); combatPtr->setParam(COMBAT_PARAM_AGGRESSIVE, 0); combatPtr->addCondition(condition); } else if (spellName == "drunk") { @@ -186,7 +190,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell duration = spell->duration; } - std::shared_ptr condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_DRUNK, duration, 0); + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_DRUNK, duration, 0); combatPtr->addCondition(condition); } else if (spellName == "soulwars fear" || spellName == "fear") { int32_t duration = 6000; @@ -195,7 +199,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell duration = spell->duration; } - const auto condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_FEARED, duration, 0); + const auto &condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_FEARED, duration, 0); combatPtr->addCondition(condition); } else if (spellName == "firefield") { combatPtr->setParam(COMBAT_PARAM_CREATEITEM, ITEM_FIREFIELD_PVP_FULL); @@ -229,7 +233,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell // If a spell has a condition, it always applies, no matter what kind of spell it is if (spell->conditionType != CONDITION_NONE) { - int32_t minDamage = std::abs(spell->conditionMinDamage); + const int32_t minDamage = std::abs(spell->conditionMinDamage); int32_t maxDamage = std::abs(spell->conditionMaxDamage); int32_t startDamage = std::abs(spell->conditionStartDamage); uint32_t tickInterval = 2000; @@ -246,7 +250,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell maxDamage = minDamage; } - std::shared_ptr condition = getDamageCondition(spell->conditionType, maxDamage, minDamage, startDamage, tickInterval); + const auto &condition = getDamageCondition(spell->conditionType, maxDamage, minDamage, startDamage, tickInterval); combatPtr->addCondition(condition); } @@ -269,7 +273,7 @@ bool Monsters::deserializeSpell(const std::shared_ptr spell, spell } bool MonsterType::loadCallback(LuaScriptInterface* scriptInterface) { - int32_t id = scriptInterface->getEvent(); + const int32_t id = scriptInterface->getEvent(); if (id == -1) { g_logger().warn("[MonsterType::loadCallback] - Event not found"); return false; @@ -307,12 +311,44 @@ bool MonsterType::loadCallback(LuaScriptInterface* scriptInterface) { return true; } +uint16_t MonsterType::getBaseSpeed() const { + return info.baseSpeed; +} + +void MonsterType::setBaseSpeed(const uint16_t initBaseSpeed) { + info.baseSpeed = initBaseSpeed; +} + +float MonsterType::getHealthMultiplier() const { + return isBoss() ? g_configManager().getFloat(RATE_BOSS_HEALTH) : g_configManager().getFloat(RATE_MONSTER_HEALTH); +} + +float MonsterType::getAttackMultiplier() const { + return isBoss() ? g_configManager().getFloat(RATE_BOSS_ATTACK) : g_configManager().getFloat(RATE_MONSTER_ATTACK); +} + +float MonsterType::getDefenseMultiplier() const { + return isBoss() ? g_configManager().getFloat(RATE_BOSS_DEFENSE) : g_configManager().getFloat(RATE_MONSTER_DEFENSE); +} + +bool MonsterType::isBoss() const { + return !info.bosstiaryClass.empty(); +} + +Monsters &Monsters::getInstance() { + return inject(); +} + +void Monsters::clear() { + monsters.clear(); +} + std::shared_ptr Monsters::getMonsterType(const std::string &name, bool silent /* = false*/) const { std::string lowerCaseName = asLowerCaseString(name); if (auto it = monsters.find(lowerCaseName); it != monsters.end() // We will only return the MonsterType if it match the exact name of the monster - && it->first.find(lowerCaseName) != it->first.npos) { + && it->first.find(lowerCaseName) != std::basic_string::npos) { return it->second; } if (!silent) { @@ -322,12 +358,12 @@ std::shared_ptr Monsters::getMonsterType(const std::string &name, b } std::shared_ptr Monsters::getMonsterTypeByRaceId(uint16_t raceId, bool isBoss /* = false*/) const { - auto bossType = g_ioBosstiary().getMonsterTypeByBossRaceId(raceId); + const auto &bossType = g_ioBosstiary().getMonsterTypeByBossRaceId(raceId); if (isBoss && bossType) { return bossType; } - auto monster_race_map = g_game().getBestiaryList(); + const auto &monster_race_map = g_game().getBestiaryList(); auto it = monster_race_map.find(raceId); if (it == monster_race_map.end()) { return nullptr; @@ -336,9 +372,9 @@ std::shared_ptr Monsters::getMonsterTypeByRaceId(uint16_t raceId, b return g_monsters().getMonsterType(it->second); } -bool Monsters::tryAddMonsterType(const std::string &name, const std::shared_ptr mType) { - std::string lowerName = asLowerCaseString(name); - if (monsters.find(lowerName) != monsters.end()) { +bool Monsters::tryAddMonsterType(const std::string &name, const std::shared_ptr &mType) { + const std::string lowerName = asLowerCaseString(name); + if (monsters.contains(lowerName)) { g_logger().debug("[{}] the monster with name '{}' already exist", __FUNCTION__, name); return false; } diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index a28903e0ad5..35c4d73050d 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -9,9 +9,13 @@ #pragma once +#include "creatures/creatures_definitions.hpp" +#include "game/game_definitions.hpp" #include "io/io_bosstiary.hpp" -#include "creatures/creature.hpp" -#include "declarations.hpp" +#include "utils/utils_definitions.hpp" + +class LuaScriptInterface; +class ConditionDamage; class Loot { public: @@ -31,7 +35,7 @@ struct spellBlock_t { spellBlock_t(const spellBlock_t &other) = delete; spellBlock_t &operator=(const spellBlock_t &other) = delete; spellBlock_t(spellBlock_t &&other) noexcept : - spell(other.spell), + spell(std::move(other.spell)), chance(other.chance), speed(other.speed), range(other.range), @@ -166,7 +170,7 @@ class MonsterType { public: MonsterType() = default; explicit MonsterType(const std::string &initName) : - name(initName), typeName(initName), nameDescription(initName), variantName("") {}; + name(initName), typeName(initName), nameDescription(initName) { } // non-copyable MonsterType(const MonsterType &) = delete; @@ -181,33 +185,21 @@ class MonsterType { MonsterInfo info; - uint16_t getBaseSpeed() const { - return info.baseSpeed; - } + uint16_t getBaseSpeed() const; - void setBaseSpeed(const uint16_t initBaseSpeed) { - info.baseSpeed = initBaseSpeed; - } + void setBaseSpeed(const uint16_t initBaseSpeed); - float getHealthMultiplier() const { - return isBoss() ? g_configManager().getFloat(RATE_BOSS_HEALTH) : g_configManager().getFloat(RATE_MONSTER_HEALTH); - } + float getHealthMultiplier() const; - float getAttackMultiplier() const { - return isBoss() ? g_configManager().getFloat(RATE_BOSS_ATTACK) : g_configManager().getFloat(RATE_MONSTER_ATTACK); - } + float getAttackMultiplier() const; - float getDefenseMultiplier() const { - return isBoss() ? g_configManager().getFloat(RATE_BOSS_DEFENSE) : g_configManager().getFloat(RATE_MONSTER_DEFENSE); - } + float getDefenseMultiplier() const; - bool isBoss() const { - return !info.bosstiaryClass.empty(); - } + bool isBoss() const; - void loadLoot(std::shared_ptr monsterType, LootBlock lootblock); + void loadLoot(const std::shared_ptr &monsterType, LootBlock lootblock) const; - bool canSpawn(const Position &pos); + bool canSpawn(const Position &pos) const; }; class MonsterSpell { @@ -217,8 +209,8 @@ class MonsterSpell { MonsterSpell(const MonsterSpell &) = delete; MonsterSpell &operator=(const MonsterSpell &) = delete; - std::string name = ""; - std::string scriptName = ""; + std::string name; + std::string scriptName; uint8_t chance = 100; uint8_t range = 0; @@ -246,7 +238,7 @@ class MonsterSpell { bool isMelee = false; Outfit_t outfit = {}; - std::string outfitMonster = ""; + std::string outfitMonster; uint16_t outfitItem = 0; ShootType_t shoot = CONST_ANI_NONE; @@ -265,24 +257,20 @@ class Monsters { Monsters(const Monsters &) = delete; Monsters &operator=(const Monsters &) = delete; - static Monsters &getInstance() { - return inject(); - } + static Monsters &getInstance(); - void clear() { - monsters.clear(); - } + void clear(); std::shared_ptr getMonsterType(const std::string &name, bool silent = false) const; std::shared_ptr getMonsterTypeByRaceId(uint16_t raceId, bool isBoss = false) const; - bool tryAddMonsterType(const std::string &name, std::shared_ptr mType); - bool deserializeSpell(std::shared_ptr spell, spellBlock_t &sb, const std::string &description = ""); + bool tryAddMonsterType(const std::string &name, const std::shared_ptr &mType); + bool deserializeSpell(const std::shared_ptr &spell, spellBlock_t &sb, const std::string &description = "") const; std::unique_ptr scriptInterface; std::map> monsters; private: - std::shared_ptr getDamageCondition(ConditionType_t conditionType, int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval); + std::shared_ptr getDamageCondition(ConditionType_t conditionType, int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval) const; }; constexpr auto g_monsters = Monsters::getInstance; diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp index 922f0210000..3a915d737b2 100644 --- a/src/creatures/monsters/spawns/spawn_monster.cpp +++ b/src/creatures/monsters/spawns/spawn_monster.cpp @@ -8,16 +8,21 @@ */ #include "creatures/monsters/spawns/spawn_monster.hpp" -#include "game/game.hpp" + +#include "config/configmanager.hpp" #include "creatures/monsters/monster.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/players/player.hpp" +#include "game/game.hpp" +#include "game/movement/position.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/events_scheduler.hpp" -#include "lua/creature/events.hpp" +#include "game/zones/zone.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" -#include "utils/pugicast.hpp" -#include "game/zones/zone.hpp" +#include "lua/creature/events.hpp" #include "map/spectators.hpp" +#include "utils/pugicast.hpp" static constexpr int32_t MONSTER_MINSPAWN_INTERVAL = 1000; // 1 second static constexpr int32_t MONSTER_MAXSPAWN_INTERVAL = 86400000; // 1 day @@ -28,7 +33,7 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { } pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filemonstername.c_str()); + const pugi::xml_parse_result result = doc.load_file(filemonstername.c_str()); if (!result) { printXMLError(__FUNCTION__, filemonstername, result); return false; @@ -39,7 +44,8 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { std::string boostedNameGet = g_game().getBoostedMonsterName(); - for (auto spawnMonsterNode : doc.child("monsters").children()) { + spawnMonsterList.reserve(100000); + for (const auto &spawnMonsterNode : doc.child("monsters").children()) { Position centerPos( pugi::cast(spawnMonsterNode.attribute("centerx").value()), pugi::cast(spawnMonsterNode.attribute("centery").value()), @@ -59,9 +65,8 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { continue; } - SpawnMonster &spawnMonster = spawnMonsterList.emplace_back(centerPos, radius); - - for (auto childMonsterNode : spawnMonsterNode.children()) { + const auto &spawnMonster = spawnMonsterList.emplace_back(std::make_shared(centerPos, radius)); + for (const auto &childMonsterNode : spawnMonsterNode.children()) { if (strcasecmp(childMonsterNode.name(), "monster") == 0) { pugi::xml_attribute nameAttribute = childMonsterNode.attribute("name"); if (!nameAttribute) { @@ -77,8 +82,8 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { dir = DIRECTION_NORTH; } - auto xOffset = pugi::cast(childMonsterNode.attribute("x").value()); - auto yOffset = pugi::cast(childMonsterNode.attribute("y").value()); + const auto xOffset = pugi::cast(childMonsterNode.attribute("x").value()); + const auto yOffset = pugi::cast(childMonsterNode.attribute("y").value()); Position pos( static_cast(centerPos.x + xOffset), static_cast(centerPos.y + yOffset), @@ -93,16 +98,25 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { uint32_t scheduleInterval = g_configManager().getNumber(DEFAULT_RESPAWN_TIME); - try { - scheduleInterval = pugi::cast(childMonsterNode.attribute("spawntime").value()); - } catch (...) { - g_logger().warn("Failed to add schedule interval to monster: {}, interval: {}. Setting to default respawn time: {}", nameAttribute.value(), childMonsterNode.attribute("spawntime").value(), scheduleInterval); + pugi::xml_attribute spawnTimeAttr = childMonsterNode.attribute("spawntime"); + if (spawnTimeAttr) { + const auto xmlSpawnTime = pugi::cast(spawnTimeAttr.value()); + if (xmlSpawnTime > 0) { + scheduleInterval = xmlSpawnTime; + } else { + g_logger().warn("Invalid spawntime value '{}' for monster '{}'. Setting to default respawn time: {}", spawnTimeAttr.value(), nameAttribute.value(), scheduleInterval); + } + } else { + g_logger().warn("Missing spawntime attribute for monster '{}'. Setting to default respawn time: {}", nameAttribute.value(), scheduleInterval); } - spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, scheduleInterval * 1000, weight); + spawnMonster->addMonster(nameAttribute.as_string(), pos, dir, scheduleInterval * 1000, weight); } } } + + // Clears unused memory that has been reserved + spawnMonsterList.shrink_to_fit(); return true; } @@ -111,16 +125,16 @@ void SpawnsMonster::startup() { return; } - for (SpawnMonster &spawnMonster : spawnMonsterList) { - spawnMonster.startup(); + for (const auto &spawnMonster : spawnMonsterList) { + spawnMonster->startup(); } started = true; } void SpawnsMonster::clear() { - for (SpawnMonster &spawnMonster : spawnMonsterList) { - spawnMonster.stopEvent(); + for (const auto &spawnMonster : spawnMonsterList) { + spawnMonster->stopEvent(); } spawnMonsterList.clear(); @@ -129,6 +143,18 @@ void SpawnsMonster::clear() { filemonstername.clear(); } +bool SpawnsMonster::isStarted() const { + return started; +} + +bool SpawnsMonster::isLoaded() const { + return loaded; +} + +std::vector> &SpawnsMonster::getspawnMonsterList() { + return spawnMonsterList; +} + bool SpawnsMonster::isInZone(const Position ¢erPos, int32_t radius, const Position &pos) { if (radius == -1) { return true; @@ -146,11 +172,30 @@ void SpawnMonster::startSpawnMonsterCheck() { } SpawnMonster::~SpawnMonster() { - for (const auto &[_, monster] : spawnedMonsterMap) { - monster->setSpawnMonster(nullptr); - } stopEvent(); - spawnMonsterMap.clear(); +} + +// moveable + +SpawnMonster::SpawnMonster(SpawnMonster &&rhs) noexcept : + spawnedMonsterMap(std::move(rhs.spawnedMonsterMap)), + spawnMonsterMap(std::move(rhs.spawnMonsterMap)), + centerPos(rhs.centerPos), + radius(rhs.radius), + interval(rhs.interval), + checkSpawnMonsterEvent(rhs.checkSpawnMonsterEvent) { } + +SpawnMonster &SpawnMonster::operator=(SpawnMonster &&rhs) noexcept { + if (this != &rhs) { + spawnMonsterMap = std::move(rhs.spawnMonsterMap); + spawnedMonsterMap = std::move(rhs.spawnedMonsterMap); + + checkSpawnMonsterEvent = rhs.checkSpawnMonsterEvent; + centerPos = rhs.centerPos; + radius = rhs.radius; + interval = rhs.interval; + } + return *this; } bool SpawnMonster::findPlayer(const Position &pos) { @@ -160,11 +205,11 @@ bool SpawnMonster::findPlayer(const Position &pos) { }); } -bool SpawnMonster::isInSpawnMonsterZone(const Position &pos) { +bool SpawnMonster::isInSpawnMonsterZone(const Position &pos) const { return SpawnsMonster::isInZone(centerPos, radius, pos); } -bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr monsterType, bool startup /*= false*/) { +bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr &monsterType, bool startup /*= false*/) { if (spawnedMonsterMap.contains(spawnMonsterId)) { return false; } @@ -182,14 +227,12 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const } monster->setDirection(sb.direction); - monster->setSpawnMonster(this); + monster->setSpawnMonster(static_self_cast()); monster->setMasterPos(sb.pos); spawnedMonsterMap[spawnMonsterId] = monster; sb.lastSpawn = OTSYS_TIME(); - g_events().eventMonsterOnSpawn(monster, sb.pos); monster->onSpawn(); - g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, sb.pos); return true; } @@ -270,7 +313,7 @@ void SpawnMonster::checkSpawnMonster() { } } -void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr mType, uint16_t interval, bool startup /*= false*/) { +void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr &mType, uint16_t interval, bool startup /*= false*/) { if (interval <= 0) { spawnMonster(spawnMonsterId, sb, mType, startup); } else { @@ -282,17 +325,22 @@ void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, cons } void SpawnMonster::cleanup() { - std::erase_if(spawnedMonsterMap, [this](const auto &entry) { - const auto &monster = entry.second; + for (auto it = spawnedMonsterMap.begin(); it != spawnedMonsterMap.end();) { + const auto &monster = it->second; if (!monster || monster->isRemoved()) { - auto spawnIt = spawnMonsterMap.find(entry.first); + auto spawnIt = spawnMonsterMap.find(it->first); if (spawnIt != spawnMonsterMap.end()) { spawnIt->second.lastSpawn = OTSYS_TIME(); } - return true; + it = spawnedMonsterMap.erase(it); + } else { + ++it; } - return false; - }); + } +} + +const Position &SpawnMonster::getCenterPos() const { + return centerPos; } bool SpawnMonster::addMonster(const std::string &name, const Position &pos, Direction dir, uint32_t scheduleInterval, uint32_t weight /*= 1*/) { @@ -303,20 +351,21 @@ bool SpawnMonster::addMonster(const std::string &name, const Position &pos, Dire break; } } - const auto monsterType = g_monsters().getMonsterType(variant + name); + const auto &monsterType = g_monsters().getMonsterType(variant + name); if (!monsterType) { g_logger().error("Can not find {}", name); return false; } - uint32_t eventschedule = g_eventsScheduler().getSpawnMonsterSchedule(); - std::string boostedMonster = g_game().getBoostedMonsterName(); + const uint32_t eventschedule = g_eventsScheduler().getSpawnMonsterSchedule(); + const std::string boostedMonster = g_game().getBoostedMonsterName(); int32_t boostedrate = 1; if (name == boostedMonster) { boostedrate = 2; } + auto rateSpawn = g_configManager().getNumber(RATE_SPAWN); // eventschedule is a whole percentage, so we need to multiply by 100 to match the order of magnitude of the other values - scheduleInterval = scheduleInterval * 100 / std::max((uint32_t)1, (g_configManager().getNumber(RATE_SPAWN) * boostedrate * eventschedule)); + scheduleInterval = scheduleInterval * 100 / std::max(static_cast(1), (rateSpawn * boostedrate * eventschedule)); if (scheduleInterval < MONSTER_MINSPAWN_INTERVAL) { g_logger().warn("[SpawnsMonster::addMonster] - {} {} spawntime cannot be less than {} seconds, set to {} by default.", name, pos.toString(), MONSTER_MINSPAWN_INTERVAL / 1000, MONSTER_MINSPAWN_INTERVAL / 1000); scheduleInterval = MONSTER_MINSPAWN_INTERVAL; @@ -360,7 +409,7 @@ bool SpawnMonster::addMonster(const std::string &name, const Position &pos, Dire return true; } -void SpawnMonster::removeMonster(std::shared_ptr monster) { +void SpawnMonster::removeMonster(const std::shared_ptr &monster) { uint32_t spawnMonsterId = 0; for (const auto &[id, m] : spawnedMonsterMap) { if (m == monster) { @@ -377,9 +426,13 @@ void SpawnMonster::removeMonsters() { } void SpawnMonster::setMonsterVariant(const std::string &variant) { - for (auto &it : spawnMonsterMap) { + for (auto &[monsterId, monsterInfo] : spawnMonsterMap) { + if (monsterId == 0) { + continue; + } + std::unordered_map, uint32_t> monsterTypes; - for (const auto &[monsterType, weight] : it.second.monsterTypes) { + for (const auto &[monsterType, weight] : monsterInfo.monsterTypes) { if (!monsterType || monsterType->typeName.empty()) { continue; } @@ -389,7 +442,7 @@ void SpawnMonster::setMonsterVariant(const std::string &variant) { monsterTypes.emplace(variantType, weight); } } - it.second.monsterTypes = monsterTypes; + monsterInfo.monsterTypes = monsterTypes; } } @@ -420,7 +473,7 @@ std::shared_ptr spawnBlock_t::getMonsterType() const { uint32_t randomWeight = uniform_random(0, totalWeight - 1); // order monsters by weight DESC std::vector, uint32_t>> orderedMonsterTypes(monsterTypes.begin(), monsterTypes.end()); - std::sort(orderedMonsterTypes.begin(), orderedMonsterTypes.end(), [](const auto &a, const auto &b) { + std::ranges::sort(orderedMonsterTypes, [](const auto &a, const auto &b) { return a.second > b.second; }); for (const auto &[mType, weight] : orderedMonsterTypes) { diff --git a/src/creatures/monsters/spawns/spawn_monster.hpp b/src/creatures/monsters/spawns/spawn_monster.hpp index caf454c41b5..d825ad73c23 100644 --- a/src/creatures/monsters/spawns/spawn_monster.hpp +++ b/src/creatures/monsters/spawns/spawn_monster.hpp @@ -9,24 +9,25 @@ #pragma once -#include "items/tile.hpp" #include "game/movement/position.hpp" +enum Direction : uint8_t; +struct Position; class Monster; class MonsterType; struct spawnBlock_t { Position pos; - std::unordered_map, uint32_t> monsterTypes; - int64_t lastSpawn; - uint32_t interval; + std::unordered_map, uint32_t> monsterTypes {}; + int64_t lastSpawn {}; + uint32_t interval {}; Direction direction; std::shared_ptr getMonsterType() const; bool hasBoss() const; }; -class SpawnMonster { +class SpawnMonster : public SharedObject { public: SpawnMonster(Position initPos, int32_t initRadius) : centerPos(initPos), radius(initRadius) { } @@ -37,29 +38,12 @@ class SpawnMonster { SpawnMonster &operator=(const SpawnMonster &) = delete; // moveable - SpawnMonster(SpawnMonster &&rhs) noexcept : - spawnedMonsterMap(std::move(rhs.spawnedMonsterMap)), - spawnMonsterMap(std::move(rhs.spawnMonsterMap)), - centerPos(rhs.centerPos), - radius(rhs.radius), - interval(rhs.interval), - checkSpawnMonsterEvent(rhs.checkSpawnMonsterEvent) { } - - SpawnMonster &operator=(SpawnMonster &&rhs) noexcept { - if (this != &rhs) { - spawnMonsterMap = std::move(rhs.spawnMonsterMap); - spawnedMonsterMap = std::move(rhs.spawnedMonsterMap); - - checkSpawnMonsterEvent = rhs.checkSpawnMonsterEvent; - centerPos = rhs.centerPos; - radius = rhs.radius; - interval = rhs.interval; - } - return *this; - } + SpawnMonster(SpawnMonster &&rhs) noexcept; + + SpawnMonster &operator=(SpawnMonster &&rhs) noexcept; bool addMonster(const std::string &name, const Position &pos, Direction dir, uint32_t interval, uint32_t weight = 1); - void removeMonster(std::shared_ptr monster); + void removeMonster(const std::shared_ptr &monster); void removeMonsters(); uint32_t getInterval() const { @@ -70,12 +54,10 @@ class SpawnMonster { void startSpawnMonsterCheck(); void stopEvent(); - bool isInSpawnMonsterZone(const Position &pos); + bool isInSpawnMonsterZone(const Position &pos) const; void cleanup(); - const Position &getCenterPos() const { - return centerPos; - } + const Position &getCenterPos() const; void setMonsterVariant(const std::string &variant); @@ -90,9 +72,9 @@ class SpawnMonster { uint32_t checkSpawnMonsterEvent = 0; static bool findPlayer(const Position &pos); - bool spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, std::shared_ptr monsterType, bool startup = false); + bool spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr &monsterType, bool startup = false); void checkSpawnMonster(); - void scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, std::shared_ptr monsterType, uint16_t interval, bool startup = false); + void scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, const std::shared_ptr &monsterType, uint16_t interval, bool startup = false); }; class SpawnsMonster { @@ -103,18 +85,12 @@ class SpawnsMonster { void startup(); void clear(); - bool isStarted() const { - return started; - } - bool isLoaded() const { - return loaded; - } - std::vector &getspawnMonsterList() { - return spawnMonsterList; - } + bool isStarted() const; + bool isLoaded() const; + std::vector> &getspawnMonsterList(); private: - std::vector spawnMonsterList; + std::vector> spawnMonsterList; std::string filemonstername; bool loaded = false; bool started = false; diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp index 2d615c022e4..e2ab99a1dd4 100644 --- a/src/creatures/npcs/npc.cpp +++ b/src/creatures/npcs/npc.cpp @@ -8,13 +8,17 @@ */ #include "creatures/npcs/npc.hpp" + +#include "config/configmanager.hpp" +#include "creatures/creature.hpp" #include "creatures/npcs/npcs.hpp" -#include "declarations.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "lua/callbacks/creaturecallback.hpp" #include "game/scheduling/dispatcher.hpp" -#include "map/spectators.hpp" #include "lib/metrics/metrics.hpp" +#include "lua/callbacks/creaturecallback.hpp" +#include "lua/global/shared_object.hpp" +#include "map/spectators.hpp" int32_t Npc::despawnRange; int32_t Npc::despawnRadius; @@ -35,7 +39,7 @@ Npc::Npc(const std::shared_ptr &npcType) : npcType(npcType) { defaultOutfit = npcType->info.outfit; currentOutfit = npcType->info.outfit; - float multiplier = g_configManager().getFloat(RATE_NPC_HEALTH); + const float multiplier = g_configManager().getFloat(RATE_NPC_HEALTH); health = npcType->info.health * multiplier; healthMax = npcType->info.healthMax * multiplier; baseSpeed = npcType->info.baseSpeed; @@ -50,10 +54,96 @@ Npc::Npc(const std::shared_ptr &npcType) : } } +Npc &Npc::getInstance() { + return inject(); +} + +std::shared_ptr Npc::getNpc() { + return static_self_cast(); +} + +std::shared_ptr Npc::getNpc() const { + return static_self_cast(); +} + +void Npc::setID() { + if (id == 0) { + id = npcAutoID++; + } +} + void Npc::addList() { g_game().addNpc(static_self_cast()); } +const std::string &Npc::getName() const { + return npcType->name; +} + +// Real npc name, set on npc creation "createNpcType(typeName)" +const std::string &Npc::getTypeName() const { + return npcType->typeName; +} + +const std::string &Npc::getNameDescription() const { + return npcType->nameDescription; +} + +std::string Npc::getDescription(int32_t) { + return strDescription + '.'; +} + +void Npc::setName(std::string newName) const { + npcType->name = std::move(newName); +} + +CreatureType_t Npc::getType() const { + return CREATURETYPE_NPC; +} + +const Position &Npc::getMasterPos() const { + return masterPos; +} + +void Npc::setMasterPos(Position pos) { + masterPos = pos; +} + +uint8_t Npc::getSpeechBubble() const { + return npcType->info.speechBubble; +} + +void Npc::setSpeechBubble(const uint8_t bubble) const { + npcType->info.speechBubble = bubble; +} + +uint16_t Npc::getCurrency() const { + return npcType->info.currencyId; +} + +void Npc::setCurrency(uint16_t currency) { + npcType->info.currencyId = currency; +} + +const std::vector &Npc::getShopItemVector(uint32_t playerGUID) const { + if (playerGUID != 0) { + auto it = shopPlayers.find(playerGUID); + if (it != shopPlayers.end() && !it->second.empty()) { + return it->second; + } + } + + return npcType->info.shopItemVector; +} + +bool Npc::isPushable() { + return npcType->info.pushable; +} + +bool Npc::isAttackable() const { + return false; +} + void Npc::removeList() { g_game().removeNpc(static_self_cast()); } @@ -65,6 +155,18 @@ bool Npc::canInteract(const Position &pos, uint32_t range /* = 4 */) { return Creature::canSee(getPosition(), pos, range, range); } +bool Npc::canSeeInvisibility() const { + return true; +} + +RespawnType Npc::getRespawnType() const { + return npcType->info.respawnType; +} + +void Npc::setSpawnNpc(const std::shared_ptr &newSpawn) { + spawnNpc = newSpawn; +} + bool Npc::isInteractingWithPlayer(uint32_t playerId) { if (playerInteractions.empty()) { return false; @@ -88,15 +190,15 @@ bool Npc::isPlayerInteractingOnTopic(uint32_t playerId, uint16_t topicId) { return it->second == topicId; } -void Npc::onCreatureAppear(std::shared_ptr creature, bool isLogin) { +void Npc::onCreatureAppear(const std::shared_ptr &creature, bool isLogin) { Creature::onCreatureAppear(creature, isLogin); - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { onPlayerAppear(player); } // onCreatureAppear(self, creature) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.creatureAppearEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(creature); @@ -107,11 +209,11 @@ void Npc::onCreatureAppear(std::shared_ptr creature, bool isLogin) { } } -void Npc::onRemoveCreature(std::shared_ptr creature, bool isLogout) { +void Npc::onRemoveCreature(const std::shared_ptr &creature, bool isLogout) { Creature::onRemoveCreature(creature, isLogout); // onCreatureDisappear(self, creature) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.creatureDisappearEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(creature); @@ -121,7 +223,7 @@ void Npc::onRemoveCreature(std::shared_ptr creature, bool isLogout) { return; } - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { removeShopPlayer(player->getGUID()); onPlayerDisappear(player); } @@ -135,7 +237,7 @@ void Npc::onCreatureMove(const std::shared_ptr &creature, const std::s Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); // onCreatureMove(self, creature, oldPosition, newPosition) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.creatureMoveEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(creature); @@ -165,7 +267,7 @@ void Npc::manageIdle() { } } -void Npc::onPlayerAppear(std::shared_ptr player) { +void Npc::onPlayerAppear(const std::shared_ptr &player) { if (player->hasFlag(PlayerFlags_t::IgnoredByNpcs) || playerSpectators.contains(player)) { return; } @@ -173,7 +275,7 @@ void Npc::onPlayerAppear(std::shared_ptr player) { manageIdle(); } -void Npc::onPlayerDisappear(std::shared_ptr player) { +void Npc::onPlayerDisappear(const std::shared_ptr &player) { removePlayerInteraction(player); if (!player->hasFlag(PlayerFlags_t::IgnoredByNpcs) && playerSpectators.contains(player)) { playerSpectators.erase(player); @@ -181,7 +283,7 @@ void Npc::onPlayerDisappear(std::shared_ptr player) { } } -void Npc::onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) { +void Npc::onCreatureSay(const std::shared_ptr &creature, SpeakClasses type, const std::string &text) { Creature::onCreatureSay(creature, type, text); if (!creature->getPlayer()) { @@ -189,7 +291,7 @@ void Npc::onCreatureSay(std::shared_ptr creature, SpeakClasses type, c } // onCreatureSay(self, creature, type, message) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.creatureSayEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(creature); @@ -212,7 +314,7 @@ void Npc::onThinkSound(uint32_t interval) { soundTicks = 0; if (!npcType->info.soundVector.empty() && (npcType->info.soundChance >= static_cast(uniform_random(1, 100)))) { - auto index = uniform_random(0, npcType->info.soundVector.size() - 1); + const auto index = uniform_random(0, npcType->info.soundVector.size() - 1); g_game().sendSingleSoundEffect(static_self_cast()->getPosition(), npcType->info.soundVector[index], getNpc()); } } @@ -222,7 +324,7 @@ void Npc::onThink(uint32_t interval) { Creature::onThink(interval); // onThink(self, interval) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.thinkEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushNumber(interval); @@ -249,7 +351,7 @@ void Npc::onThink(uint32_t interval) { } } -void Npc::onPlayerBuyItem(std::shared_ptr player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore, bool inBackpacks) { +void Npc::onPlayerBuyItem(const std::shared_ptr &player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore, bool inBackpacks) { if (player == nullptr) { g_logger().error("[Npc::onPlayerBuyItem] - Player is nullptr"); return; @@ -261,10 +363,10 @@ void Npc::onPlayerBuyItem(std::shared_ptr player, uint16_t itemId, uint8 return; } - uint32_t shoppingBagPrice = 20; - uint32_t shoppingBagSlots = 20; + constexpr uint32_t shoppingBagPrice = 20; + constexpr uint32_t shoppingBagSlots = 20; const ItemType &itemType = Item::items[itemId]; - if (std::shared_ptr tile = ignore ? player->getTile() : nullptr; tile) { + if (const std::shared_ptr &tile = ignore ? player->getTile() : nullptr; tile) { double slotsNedeed; if (itemType.stackable) { slotsNedeed = inBackpacks ? std::ceil(std::ceil(static_cast(amount) / itemType.stackSize) / shoppingBagSlots) : std::ceil(static_cast(amount) / itemType.stackSize); @@ -286,7 +388,7 @@ void Npc::onPlayerBuyItem(std::shared_ptr player, uint16_t itemId, uint8 } } - uint32_t totalCost = buyPrice * amount; + const uint32_t totalCost = buyPrice * amount; uint32_t bagsCost = 0; if (inBackpacks && itemType.stackable) { bagsCost = shoppingBagPrice * static_cast(std::ceil(std::ceil(static_cast(amount) / itemType.stackSize) / shoppingBagSlots)); @@ -306,7 +408,7 @@ void Npc::onPlayerBuyItem(std::shared_ptr player, uint16_t itemId, uint8 } // npc:onBuyItem(player, itemId, subType, amount, ignore, inBackpacks, totalCost) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.playerBuyEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(player); @@ -323,18 +425,18 @@ void Npc::onPlayerBuyItem(std::shared_ptr player, uint16_t itemId, uint8 } } -void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore) { +void Npc::onPlayerSellItem(const std::shared_ptr &player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore) { uint64_t totalPrice = 0; - onPlayerSellItem(std::move(player), itemId, subType, amount, ignore, totalPrice); + onPlayerSellItem(player, itemId, subType, amount, ignore, totalPrice); } void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, uint64_t totalPrice) { - std::shared_ptr player = g_game().getPlayerByID(playerId); + const auto &player = g_game().getPlayerByID(playerId); if (!player) { return; } if (itemId == ITEM_GOLD_POUCH) { - auto container = player->getLootPouch(); + const auto &container = player->getLootPouch(); if (!container) { return; } @@ -346,7 +448,7 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u hasMore = true; break; } - auto item = *it; + const auto &item = *it; if (!item) { continue; } @@ -357,7 +459,7 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u toSellCount += item->getItemAmount(); } } - for (auto &[m_itemId, amount] : toSell) { + for (const auto &[m_itemId, amount] : toSell) { onPlayerSellItem(player, m_itemId, 0, amount, ignore, totalPrice, container); } auto ss = std::stringstream(); @@ -379,7 +481,7 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u } } -void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore, uint64_t &totalPrice, std::shared_ptr parent /*= nullptr*/) { +void Npc::onPlayerSellItem(const std::shared_ptr &player, uint16_t itemId, uint8_t subType, uint16_t amount, bool ignore, uint64_t &totalPrice, const std::shared_ptr &parent /*= nullptr*/) { if (!player) { return; } @@ -453,7 +555,7 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint } g_metrics().addCounter("balance_increase", totalCost, { { "player", player->getName() }, { "context", "npc_sale" } }); } else { - std::shared_ptr newItem = Item::CreateItem(getCurrency(), totalCost); + const auto &newItem = Item::CreateItem(getCurrency(), totalCost); if (newItem) { g_game().internalPlayerAddItem(player, newItem, true); } @@ -461,7 +563,7 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint } // npc:onSellItem(player, itemId, subType, amount, ignore, itemName, totalCost) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.playerSellEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(player); @@ -478,13 +580,13 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint } } -void Npc::onPlayerCheckItem(std::shared_ptr player, uint16_t itemId, uint8_t subType) { +void Npc::onPlayerCheckItem(const std::shared_ptr &player, uint16_t itemId, uint8_t subType) { if (!player) { return; } // onPlayerCheckItem(self, player, itemId, subType) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.playerLookEvent)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(player); @@ -497,14 +599,14 @@ void Npc::onPlayerCheckItem(std::shared_ptr player, uint16_t itemId, uin } } -void Npc::onPlayerCloseChannel(std::shared_ptr creature) { - std::shared_ptr player = creature->getPlayer(); +void Npc::onPlayerCloseChannel(const std::shared_ptr &creature) { + const auto &player = creature->getPlayer(); if (!player) { return; } // onPlayerCloseChannel(npc, player) - CreatureCallback callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); + auto callback = CreatureCallback(npcType->info.scriptInterface, getNpc()); if (callback.startScriptInterface(npcType->info.playerCloseChannel)) { callback.pushSpecificCreature(static_self_cast()); callback.pushCreature(player); @@ -527,13 +629,13 @@ void Npc::onThinkYell(uint32_t interval) { yellTicks = 0; if (!npcType->info.voiceVector.empty() && (npcType->info.yellChance >= static_cast(uniform_random(1, 100)))) { - uint32_t index = uniform_random(0, npcType->info.voiceVector.size() - 1); - const voiceBlock_t &vb = npcType->info.voiceVector[index]; + const uint32_t index = uniform_random(0, npcType->info.voiceVector.size() - 1); + const auto &[text, yellText] = npcType->info.voiceVector[index]; - if (vb.yellText) { - g_game().internalCreatureSay(static_self_cast(), TALKTYPE_YELL, vb.text, false); + if (yellText) { + g_game().internalCreatureSay(static_self_cast(), TALKTYPE_YELL, text, false); } else { - g_game().internalCreatureSay(static_self_cast(), TALKTYPE_SAY, vb.text, false); + g_game().internalCreatureSay(static_self_cast(), TALKTYPE_SAY, text, false); } } } @@ -575,7 +677,7 @@ void Npc::onPlacedCreature() { } void Npc::loadPlayerSpectators() { - auto spec = Spectators().find(position, true); + const auto &spec = Spectators().find(position, true); for (const auto &creature : spec) { if (!creature->getPlayer()->hasFlag(PlayerFlags_t::IgnoredByNpcs)) { playerSpectators.emplace(creature->getPlayer()); @@ -608,7 +710,7 @@ bool Npc::isInSpawnRange(const Position &pos) const { } void Npc::setPlayerInteraction(uint32_t playerId, uint16_t topicId /*= 0*/) { - std::shared_ptr creature = g_game().getCreatureByID(playerId); + const auto &creature = g_game().getCreatureByID(playerId); if (!creature) { return; } @@ -621,7 +723,7 @@ void Npc::setPlayerInteraction(uint32_t playerId, uint16_t topicId /*= 0*/) { playerInteractions[playerId] = topicId; } -void Npc::removePlayerInteraction(std::shared_ptr player) { +void Npc::removePlayerInteraction(const std::shared_ptr &player) { auto view = std::ranges::remove(playerInteractionsOrder, player->getID()); playerInteractionsOrder.erase(view.begin(), view.end()); if (playerInteractions.contains(player->getID())) { @@ -645,12 +747,12 @@ bool Npc::canWalkTo(const Position &fromPos, Direction dir) { return false; } - Position toPos = getNextPosition(dir, fromPos); + const Position toPos = getNextPosition(dir, fromPos); if (!SpawnsNpc::isInZone(masterPos, npcType->info.walkRadius, toPos)) { return false; } - std::shared_ptr toTile = g_game().map.getTile(toPos); + const auto &toTile = g_game().map.getTile(toPos); if (!toTile || toTile->queryAdd(0, getNpc(), 1, 0) != RETURNVALUE_NOERROR) { return false; } @@ -680,7 +782,7 @@ bool Npc::getRandomStep(Direction &moveDirection) { std::ranges::shuffle(directionvector, getRandomGenerator()); for (const Position &creaturePos = getPosition(); - Direction direction : directionvector) { + const Direction &direction : directionvector) { if (canWalkTo(creaturePos, direction)) { moveDirection = direction; return true; @@ -689,8 +791,12 @@ bool Npc::getRandomStep(Direction &moveDirection) { return false; } +void Npc::setNormalCreatureLight() { + internalLight = npcType->info.light; +} + bool Npc::isShopPlayer(uint32_t playerGUID) const { - return shopPlayers.find(playerGUID) != shopPlayers.end(); + return shopPlayers.contains(playerGUID); } void Npc::addShopPlayer(uint32_t playerGUID, const std::vector &shopItems) { @@ -702,7 +808,7 @@ void Npc::removeShopPlayer(uint32_t playerGUID) { } void Npc::closeAllShopWindows() { - for (const auto &[playerGUID, shopBlock] : shopPlayers) { + for (const auto &playerGUID : shopPlayers | std::views::keys) { const auto &player = g_game().getPlayerByGUID(playerGUID); if (player) { player->closeShopWindow(); @@ -711,7 +817,7 @@ void Npc::closeAllShopWindows() { shopPlayers.clear(); } -void Npc::handlePlayerMove(std::shared_ptr player, const Position &newPos) { +void Npc::handlePlayerMove(const std::shared_ptr &player, const Position &newPos) { if (!canInteract(newPos)) { onPlayerCloseChannel(player); } else if (canInteract(newPos) && !playerInteractionsOrder.empty() && playerInteractionsOrder.back() == player->getID()) { diff --git a/src/creatures/npcs/npc.hpp b/src/creatures/npcs/npc.hpp index 382ab250156..dc3e16961f1 100644 --- a/src/creatures/npcs/npc.hpp +++ b/src/creatures/npcs/npc.hpp @@ -9,12 +9,13 @@ #pragma once -#include "creatures/npcs/npcs.hpp" -#include "creatures/players/player.hpp" -#include "declarations.hpp" -#include "items/tile.hpp" -#include "lib/di/container.hpp" +#include "creatures/creature.hpp" +enum Direction : uint8_t; +struct Position; +class NpcType; +class Player; +class Tile; class Creature; class Game; class SpawnNpc; @@ -32,126 +33,71 @@ class Npc final : public Creature { Npc(const Npc &) = delete; void operator=(const std::shared_ptr &) = delete; - static Npc &getInstance() { - return inject(); - } + static Npc &getInstance(); - std::shared_ptr getNpc() override { - return static_self_cast(); - } - std::shared_ptr getNpc() const override { - return static_self_cast(); - } + std::shared_ptr getNpc() override; + std::shared_ptr getNpc() const override; - void setID() override { - if (id == 0) { - id = npcAutoID++; - } - } + void setID() override; void removeList() override; void addList() override; - const std::string &getName() const override { - return npcType->name; - } + const std::string &getName() const override; // Real npc name, set on npc creation "createNpcType(typeName)" - const std::string &getTypeName() const override { - return npcType->typeName; - } - const std::string &getNameDescription() const override { - return npcType->nameDescription; - } - std::string getDescription(int32_t) override { - return strDescription + '.'; - } - - void setName(std::string newName) { - npcType->name = std::move(newName); - } - - CreatureType_t getType() const override { - return CREATURETYPE_NPC; - } - - const Position &getMasterPos() const { - return masterPos; - } - void setMasterPos(Position pos) { - masterPos = pos; - } - - uint8_t getSpeechBubble() const override { - return npcType->info.speechBubble; - } - void setSpeechBubble(const uint8_t bubble) { - npcType->info.speechBubble = bubble; - } - - uint16_t getCurrency() const { - return npcType->info.currencyId; - } - void setCurrency(uint16_t currency) { - npcType->info.currencyId = currency; - } - - const std::vector &getShopItemVector(uint32_t playerGUID) const { - if (playerGUID != 0) { - auto it = shopPlayers.find(playerGUID); - if (it != shopPlayers.end() && !it->second.empty()) { - return it->second; - } - } - - return npcType->info.shopItemVector; - } - - bool isPushable() override { - return npcType->info.pushable; - } - - bool isAttackable() const override { - return false; - } + const std::string &getTypeName() const override; + const std::string &getNameDescription() const override; + std::string getDescription(int32_t) override; + + void setName(std::string newName) const; + + CreatureType_t getType() const override; + + const Position &getMasterPos() const; + void setMasterPos(Position pos); + + uint8_t getSpeechBubble() const override; + void setSpeechBubble(const uint8_t bubble) const; + + uint16_t getCurrency() const; + void setCurrency(uint16_t currency); + + const std::vector &getShopItemVector(uint32_t playerGUID) const; + + bool isPushable() override; + + bool isAttackable() const override; bool canInteract(const Position &pos, uint32_t range = 4); - bool canSeeInvisibility() const override { - return true; - } - RespawnType getRespawnType() const { - return npcType->info.respawnType; - } - void setSpawnNpc(const std::shared_ptr &newSpawn) { - spawnNpc = newSpawn; - } + bool canSeeInvisibility() const override; + RespawnType getRespawnType() const; + void setSpawnNpc(const std::shared_ptr &newSpawn); void setPlayerInteraction(uint32_t playerId, uint16_t topicId = 0); - void removePlayerInteraction(std::shared_ptr player); + void removePlayerInteraction(const std::shared_ptr &player); void resetPlayerInteractions(); bool isInteractingWithPlayer(uint32_t playerId); bool isPlayerInteractingOnTopic(uint32_t playerId, uint16_t topicId); - void onCreatureAppear(std::shared_ptr creature, bool isLogin) override; - void onRemoveCreature(std::shared_ptr creature, bool isLogout) override; + void onCreatureAppear(const std::shared_ptr &creature, bool isLogin) override; + void onRemoveCreature(const std::shared_ptr &creature, bool isLogout) override; void onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) override; - void onCreatureSay(std::shared_ptr creature, SpeakClasses type, const std::string &text) override; + void onCreatureSay(const std::shared_ptr &creature, SpeakClasses type, const std::string &text) override; void onThink(uint32_t interval) override; - void onPlayerBuyItem(std::shared_ptr player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore, bool inBackpacks); + void onPlayerBuyItem(const std::shared_ptr &player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore, bool inBackpacks); void onPlayerSellAllLoot(uint32_t playerId, uint16_t itemid, bool ignore, uint64_t totalPrice); - void onPlayerSellItem(std::shared_ptr player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore); - void onPlayerSellItem(std::shared_ptr player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore, uint64_t &totalPrice, std::shared_ptr parent = nullptr); - void onPlayerCheckItem(std::shared_ptr player, uint16_t itemid, uint8_t count); - void onPlayerCloseChannel(std::shared_ptr creature); + void onPlayerSellItem(const std::shared_ptr &player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore); + void onPlayerSellItem(const std::shared_ptr &player, uint16_t itemid, uint8_t count, uint16_t amount, bool ignore, uint64_t &totalPrice, const std::shared_ptr &parent = nullptr); + void onPlayerCheckItem(const std::shared_ptr &player, uint16_t itemid, uint8_t count); + void onPlayerCloseChannel(const std::shared_ptr &creature); void onPlacedCreature() override; bool canWalkTo(const Position &fromPos, Direction dir); bool getNextStep(Direction &nextDirection, uint32_t &flags) override; bool getRandomStep(Direction &moveDirection); - void setNormalCreatureLight() override { - internalLight = npcType->info.light; - } + void setNormalCreatureLight() override; bool isShopPlayer(uint32_t playerGUID) const; @@ -195,10 +141,10 @@ class Npc final : public Creature { friend class LuaScriptInterface; friend class Map; - void onPlayerAppear(std::shared_ptr player); - void onPlayerDisappear(std::shared_ptr player); + void onPlayerAppear(const std::shared_ptr &player); + void onPlayerDisappear(const std::shared_ptr &player); void manageIdle(); - void handlePlayerMove(std::shared_ptr player, const Position &newPos); + void handlePlayerMove(const std::shared_ptr &player, const Position &newPos); void loadPlayerSpectators(); }; diff --git a/src/creatures/npcs/npcs.cpp b/src/creatures/npcs/npcs.cpp index 7678daf38b0..53ed757336f 100644 --- a/src/creatures/npcs/npcs.cpp +++ b/src/creatures/npcs/npcs.cpp @@ -7,17 +7,18 @@ * Website: https://docs.opentibiabr.com/ */ -#include "declarations.hpp" -#include "creatures/combat/combat.hpp" -#include "lua/scripts/lua_environment.hpp" -#include "creatures/combat/spells.hpp" #include "creatures/npcs/npcs.hpp" -#include "lua/scripts/scripts.hpp" + +#include "config/configmanager.hpp" #include "game/game.hpp" +#include "lua/scripts/lua_environment.hpp" +#include "lua/scripts/luascript.hpp" +#include "lua/scripts/scripts.hpp" +#include "lib/di/container.hpp" -bool NpcType::canSpawn(const Position &pos) { +bool NpcType::canSpawn(const Position &pos) const { bool canSpawn = true; - bool isDay = g_game().gameIsDay(); + const bool isDay = g_game().gameIsDay(); if ((isDay && info.respawnType.period == RESPAWNPERIOD_NIGHT) || (!isDay && info.respawnType.period == RESPAWNPERIOD_DAY)) { // It will ignore day and night if underground @@ -28,7 +29,7 @@ bool NpcType::canSpawn(const Position &pos) { } bool NpcType::loadCallback(LuaScriptInterface* scriptInterface) { - int32_t id = scriptInterface->getEvent(); + const int32_t id = scriptInterface->getEvent(); if (id == -1) { g_logger().warn("[NpcType::loadCallback] - Event not found"); return false; @@ -82,32 +83,32 @@ void NpcType::loadShop(const std::shared_ptr &npcType, ShopBlock shopBl } // Check if the item already exists in the shop vector and ignore it - if (std::any_of(npcType->info.shopItemVector.begin(), npcType->info.shopItemVector.end(), [&shopBlock](const auto &shopIterator) { + if (std::ranges::any_of(npcType->info.shopItemVector, [&shopBlock](const auto &shopIterator) { return shopIterator == shopBlock; })) { return; } if (shopBlock.childShop.empty()) { - bool isContainer = iType.isContainer(); + const bool &isContainer = iType.isContainer(); if (isContainer) { for (const ShopBlock &child : shopBlock.childShop) { shopBlock.childShop.push_back(child); } } } - npcType->info.shopItemVector.push_back(shopBlock); + npcType->info.shopItemVector.emplace_back(shopBlock); info.speechBubble = SPEECHBUBBLE_TRADE; } bool Npcs::load(bool loadLibs /* = true*/, bool loadNpcs /* = true*/, bool reloading /* = false*/) const { if (loadLibs) { - auto coreFolder = g_configManager().getString(CORE_DIRECTORY); + const auto coreFolder = g_configManager().getString(CORE_DIRECTORY); return g_luaEnvironment().loadFile(coreFolder + "/npclib/load.lua", "load.lua") == 0; } if (loadNpcs) { - auto datapackFolder = g_configManager().getString(DATA_DIRECTORY); + const auto datapackFolder = g_configManager().getString(DATA_DIRECTORY); return g_scripts().loadScripts(datapackFolder + "/npc", false, reloading); } return false; @@ -129,8 +130,12 @@ bool Npcs::reload() { return false; } +Npcs &Npcs::getInstance() { + return inject(); +} + std::shared_ptr Npcs::getNpcType(const std::string &name, bool create /* = false*/) { - std::string key = asLowerCaseString(name); + const std::string key = asLowerCaseString(name); auto it = npcs.find(key); if (it != npcs.end()) { diff --git a/src/creatures/npcs/npcs.hpp b/src/creatures/npcs/npcs.hpp index ab5e700caea..b91e1547c07 100644 --- a/src/creatures/npcs/npcs.hpp +++ b/src/creatures/npcs/npcs.hpp @@ -9,8 +9,10 @@ #pragma once -#include "creatures/creature.hpp" -#include "lib/di/container.hpp" +#include "creatures/creatures_definitions.hpp" +#include "utils/utils_definitions.hpp" + +class LuaScriptInterface; class Shop { public: @@ -23,7 +25,7 @@ class Shop { ShopBlock shopBlock; }; -class NpcType : public SharedObject { +class NpcType final : public SharedObject { struct NpcInfo { LuaScriptInterface* scriptInterface {}; @@ -90,7 +92,7 @@ class NpcType : public SharedObject { void loadShop(const std::shared_ptr &npcType, ShopBlock shopBlock); bool loadCallback(LuaScriptInterface* scriptInterface); - bool canSpawn(const Position &pos); + bool canSpawn(const Position &pos) const; }; class Npcs { @@ -100,9 +102,7 @@ class Npcs { Npcs(const Npcs &) = delete; Npcs &operator=(const Npcs &) = delete; - static Npcs &getInstance() { - return inject(); - } + static Npcs &getInstance(); std::shared_ptr getNpcType(const std::string &name, bool create = false); diff --git a/src/creatures/npcs/spawns/spawn_npc.cpp b/src/creatures/npcs/spawns/spawn_npc.cpp index 0976e96b68f..404f6ce588e 100644 --- a/src/creatures/npcs/spawns/spawn_npc.cpp +++ b/src/creatures/npcs/spawns/spawn_npc.cpp @@ -8,14 +8,17 @@ */ #include "creatures/npcs/spawns/spawn_npc.hpp" + #include "creatures/npcs/npc.hpp" +#include "creatures/npcs/npcs.hpp" +#include "creatures/players/player.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 "utils/pugicast.hpp" +#include "lua/creature/events.hpp" #include "map/spectators.hpp" +#include "utils/pugicast.hpp" static constexpr int32_t MINSPAWN_INTERVAL = 1000; // 1 second static constexpr int32_t MAXSPAWN_INTERVAL = 86400000; // 1 day @@ -26,7 +29,7 @@ bool SpawnsNpc::loadFromXml(const std::string &fileNpcName) { } pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(fileNpcName.c_str()); + const pugi::xml_parse_result result = doc.load_file(fileNpcName.c_str()); if (!result) { printXMLError(__FUNCTION__, fileNpcName, result); return false; @@ -35,7 +38,7 @@ bool SpawnsNpc::loadFromXml(const std::string &fileNpcName) { setFileName(fileNpcName); setLoaded(true); - for (auto spawnNode : doc.child("npcs").children()) { + for (const auto &spawnNode : doc.child("npcs").children()) { Position centerPos( pugi::cast(spawnNode.attribute("centerx").value()), pugi::cast(spawnNode.attribute("centery").value()), @@ -57,7 +60,7 @@ bool SpawnsNpc::loadFromXml(const std::string &fileNpcName) { const auto &spawnNpc = spawnNpcList.emplace_back(std::make_shared(centerPos, radius)); - for (auto childNode : spawnNode.children()) { + for (const auto &childNode : spawnNode.children()) { if (strcasecmp(childNode.name(), "npc") == 0) { pugi::xml_attribute nameAttribute = childNode.attribute("name"); if (!nameAttribute) { @@ -73,14 +76,14 @@ bool SpawnsNpc::loadFromXml(const std::string &fileNpcName) { dir = DIRECTION_NORTH; } - auto xOffset = pugi::cast(childNode.attribute("x").value()); - auto yOffset = pugi::cast(childNode.attribute("y").value()); + const auto xOffset = pugi::cast(childNode.attribute("x").value()); + const auto yOffset = pugi::cast(childNode.attribute("y").value()); Position pos( static_cast(centerPos.x + xOffset), static_cast(centerPos.y + yOffset), centerPos.z ); - int64_t interval = pugi::cast(childNode.attribute("spawntime").value()) * 1000; + const int64_t interval = pugi::cast(childNode.attribute("spawntime").value()) * 1000; if (interval >= MINSPAWN_INTERVAL && interval <= MAXSPAWN_INTERVAL) { spawnNpc->addNpc(nameAttribute.as_string(), pos, dir, static_cast(interval)); } else { @@ -119,6 +122,30 @@ void SpawnsNpc::clear() { fileName.clear(); } +bool SpawnsNpc::isStarted() const { + return started; +} + +bool SpawnsNpc::setStarted(bool setStarted) { + return started = setStarted; +} + +bool SpawnsNpc::isLoaded() const { + return loaded; +} + +bool SpawnsNpc::setLoaded(bool setLoaded) { + return loaded = setLoaded; +} + +std::string SpawnsNpc::setFileName(std::string setName) { + return fileName = std::move(setName); +} + +std::vector> &SpawnsNpc::getSpawnNpcList() { + return spawnNpcList; +} + bool SpawnsNpc::isInZone(const Position ¢erPos, int32_t radius, const Position &pos) { if (radius == -1) { return true; @@ -136,8 +163,11 @@ void SpawnNpc::startSpawnNpcCheck() { } SpawnNpc::~SpawnNpc() { - for (const auto &it : spawnedNpcMap) { - auto npc = it.second; + for (const auto &[spawnId, npc] : spawnedNpcMap) { + if (spawnId == 0) { + continue; + } + npc->setSpawnNpc(nullptr); } } @@ -149,7 +179,7 @@ bool SpawnNpc::findPlayer(const Position &pos) { }); } -bool SpawnNpc::isInSpawnNpcZone(const Position &pos) { +bool SpawnNpc::isInSpawnNpcZone(const Position &pos) const { return SpawnsNpc::isInZone(centerPos, radius, pos); } @@ -172,17 +202,21 @@ bool SpawnNpc::spawnNpc(uint32_t spawnId, const std::shared_ptr &npcTyp spawnedNpcMap.insert(spawned_pair(spawnId, npc)); spawnNpcMap[spawnId].lastSpawnNpc = OTSYS_TIME(); - - g_events().eventNpcOnSpawn(npc, pos); - g_callbacks().executeCallback(EventCallback_t::npcOnSpawn, &EventCallback::npcOnSpawn, npc, pos); return true; } +uint32_t SpawnNpc::getInterval() const { + return interval; +} + void SpawnNpc::startup() { - for (const auto &it : spawnNpcMap) { - uint32_t spawnId = it.first; - const spawnBlockNpc_t &sb = it.second; - spawnNpc(spawnId, sb.npcType, sb.pos, sb.direction, true); + for (const auto &[spawnId, npcInfo] : spawnNpcMap) { + if (spawnId == 0) { + continue; + } + + const auto &[pos, npcType, lastSpawnNpc, _, direction] = npcInfo; + spawnNpc(spawnId, npcType, pos, direction, true); } } @@ -191,25 +225,24 @@ void SpawnNpc::checkSpawnNpc() { cleanup(); - for (auto &it : spawnNpcMap) { - uint32_t spawnId = it.first; - if (spawnedNpcMap.find(spawnId) != spawnedNpcMap.end()) { + for (auto &[spawnId, npcInfo] : spawnNpcMap) { + if (spawnedNpcMap.contains(spawnId)) { continue; } - spawnBlockNpc_t &sb = it.second; - if (!sb.npcType->canSpawn(sb.pos)) { - sb.lastSpawnNpc = OTSYS_TIME(); + auto &[pos, npcType, lastSpawnNpc, mapInterval, direction] = npcInfo; + if (!npcType->canSpawn(pos)) { + lastSpawnNpc = OTSYS_TIME(); continue; } - if (OTSYS_TIME() >= sb.lastSpawnNpc + sb.interval) { - if (findPlayer(sb.pos)) { - sb.lastSpawnNpc = OTSYS_TIME(); + if (OTSYS_TIME() >= lastSpawnNpc + mapInterval) { + if (findPlayer(pos)) { + lastSpawnNpc = OTSYS_TIME(); continue; } - scheduleSpawnNpc(spawnId, sb, 3 * NONBLOCKABLE_SPAWN_NPC_INTERVAL); + scheduleSpawnNpc(spawnId, npcInfo, 3 * NONBLOCKABLE_SPAWN_NPC_INTERVAL); } } @@ -235,7 +268,7 @@ void SpawnNpc::cleanup() { auto it = spawnedNpcMap.begin(); while (it != spawnedNpcMap.end()) { uint32_t spawnId = it->first; - auto npc = it->second; + const auto &npc = it->second; if (npc->isRemoved()) { spawnNpcMap[spawnId].lastSpawnNpc = OTSYS_TIME(); it = spawnedNpcMap.erase(it); @@ -261,12 +294,12 @@ bool SpawnNpc::addNpc(const std::string &name, const Position &pos, Direction di sb.interval = scheduleInterval; sb.lastSpawnNpc = 0; - uint32_t spawnId = spawnNpcMap.size() + 1; + const uint32_t spawnId = spawnNpcMap.size() + 1; spawnNpcMap[spawnId] = sb; return true; } -void SpawnNpc::removeNpc(std::shared_ptr npc) { +void SpawnNpc::removeNpc(const std::shared_ptr &npc) { for (auto it = spawnedNpcMap.begin(), end = spawnedNpcMap.end(); it != end; ++it) { if (it->second == npc) { spawnedNpcMap.erase(it); diff --git a/src/creatures/npcs/spawns/spawn_npc.hpp b/src/creatures/npcs/spawns/spawn_npc.hpp index b0d0ab8622a..38bbb55aee2 100644 --- a/src/creatures/npcs/spawns/spawn_npc.hpp +++ b/src/creatures/npcs/spawns/spawn_npc.hpp @@ -10,7 +10,6 @@ #pragma once #include "game/movement/position.hpp" -#include "items/tile.hpp" class Npc; class NpcType; @@ -23,28 +22,26 @@ struct spawnBlockNpc_t { Direction direction; }; -class SpawnNpc : public SharedObject { +class SpawnNpc final : public SharedObject { public: SpawnNpc(Position initPos, int32_t initRadius) : centerPos(initPos), radius(initRadius) { } - ~SpawnNpc(); + ~SpawnNpc() override; // non-copyable SpawnNpc(const SpawnNpc &) = delete; SpawnNpc &operator=(const SpawnNpc &) = delete; bool addNpc(const std::string &name, const Position &pos, Direction dir, uint32_t interval); - void removeNpc(std::shared_ptr npc); + void removeNpc(const std::shared_ptr &npc); - uint32_t getInterval() const { - return interval; - } + uint32_t getInterval() const; void startup(); void startSpawnNpcCheck(); void stopEvent(); - bool isInSpawnNpcZone(const Position &pos); + bool isInSpawnNpcZone(const Position &pos) const; void cleanup(); private: @@ -76,27 +73,15 @@ class SpawnsNpc { void startup(); void clear(); - bool isStarted() const { - return started; - } - bool setStarted(bool setStarted) { - return started = setStarted; - } - - bool isLoaded() const { - return loaded; - } - bool setLoaded(bool setLoaded) { - return loaded = setLoaded; - } - - std::string setFileName(std::string setName) { - return fileName = std::move(setName); - } - - std::vector> &getSpawnNpcList() { - return spawnNpcList; - } + bool isStarted() const; + bool setStarted(bool setStarted); + + bool isLoaded() const; + bool setLoaded(bool setLoaded); + + std::string setFileName(std::string setName); + + std::vector> &getSpawnNpcList(); private: std::vector> spawnNpcList; diff --git a/src/creatures/players/achievement/player_achievement.cpp b/src/creatures/players/achievement/player_achievement.cpp index 5a9c1f55858..0be4244b25e 100644 --- a/src/creatures/players/achievement/player_achievement.cpp +++ b/src/creatures/players/achievement/player_achievement.cpp @@ -7,7 +7,7 @@ * Website: https://docs.opentibiabr.com/ */ -#include "player_achievement.hpp" +#include "creatures/players/achievement/player_achievement.hpp" #include "creatures/players/player.hpp" #include "game/game.hpp" @@ -21,7 +21,7 @@ bool PlayerAchievement::add(uint16_t id, bool message /* = true*/, uint32_t time return false; } - const Achievement &achievement = g_game().getAchievementById(id); + const auto &achievement = g_game().getAchievementById(id); if (achievement.id == 0) { return false; } @@ -43,12 +43,12 @@ bool PlayerAchievement::remove(uint16_t id) { return false; } - Achievement achievement = g_game().getAchievementById(id); + const auto achievement = g_game().getAchievementById(id); if (achievement.id == 0) { return false; } - if (auto it = std::find_if(m_achievementsUnlocked.begin(), m_achievementsUnlocked.end(), [id](auto achievement_it) { + if (auto it = std::ranges::find_if(m_achievementsUnlocked, [id](auto achievement_it) { return achievement_it.first == id; }); it != m_achievementsUnlocked.end()) { @@ -67,7 +67,7 @@ bool PlayerAchievement::isUnlocked(uint16_t id) const { return false; } - if (auto it = std::find_if(m_achievementsUnlocked.begin(), m_achievementsUnlocked.end(), [id](auto achievement_it) { + if (auto it = std::ranges::find_if(m_achievementsUnlocked, [id](auto achievement_it) { return achievement_it.first == id; }); it != m_achievementsUnlocked.end()) { @@ -78,17 +78,17 @@ bool PlayerAchievement::isUnlocked(uint16_t id) const { } uint16_t PlayerAchievement::getPoints() const { - auto kvScoped = m_player.kv()->scoped("achievements")->get("points"); + const auto kvScoped = m_player.kv()->scoped("achievements")->get("points"); return kvScoped ? static_cast(kvScoped->getNumber()) : 0; } -void PlayerAchievement::addPoints(uint16_t toAddPoints) { - auto oldPoints = getPoints(); +void PlayerAchievement::addPoints(uint16_t toAddPoints) const { + const auto oldPoints = getPoints(); m_player.kv()->scoped("achievements")->set("points", oldPoints + toAddPoints); } -void PlayerAchievement::removePoints(uint16_t points) { - auto oldPoints = getPoints(); +void PlayerAchievement::removePoints(uint16_t points) const { + const auto oldPoints = getPoints(); m_player.kv()->scoped("achievements")->set("points", oldPoints - std::min(oldPoints, points)); } @@ -112,11 +112,11 @@ void PlayerAchievement::loadUnlockedAchievements() { } } -void PlayerAchievement::sendUnlockedSecretAchievements() { +void PlayerAchievement::sendUnlockedSecretAchievements() const { std::vector> achievementsUnlocked; uint16_t unlockedSecret = 0; for (const auto &[achievId, achievCreatedTime] : getUnlockedAchievements()) { - Achievement achievement = g_game().getAchievementById(achievId); + const auto &achievement = g_game().getAchievementById(achievId); if (achievement.id == 0) { continue; } diff --git a/src/creatures/players/achievement/player_achievement.hpp b/src/creatures/players/achievement/player_achievement.hpp index e0c027e5808..946be626e0e 100644 --- a/src/creatures/players/achievement/player_achievement.hpp +++ b/src/creatures/players/achievement/player_achievement.hpp @@ -15,8 +15,8 @@ class KV; struct Achievement { Achievement() = default; - std::string name; - std::string description; + std::string name {}; + std::string description {}; bool secret = false; @@ -33,11 +33,11 @@ class PlayerAchievement { bool remove(uint16_t id); [[nodiscard]] bool isUnlocked(uint16_t id) const; [[nodiscard]] uint16_t getPoints() const; - void addPoints(uint16_t toAddPoints); - void removePoints(uint16_t toRemovePoints); + void addPoints(uint16_t toAddPoints) const; + void removePoints(uint16_t toRemovePoints) const; [[nodiscard]] std::vector> getUnlockedAchievements() const; void loadUnlockedAchievements(); - void sendUnlockedSecretAchievements(); + void sendUnlockedSecretAchievements() const; const std::shared_ptr &getUnlockedKV(); private: diff --git a/src/creatures/players/cyclopedia/player_badge.cpp b/src/creatures/players/cyclopedia/player_badge.cpp index b509ef041e3..c27e98cb1aa 100644 --- a/src/creatures/players/cyclopedia/player_badge.cpp +++ b/src/creatures/players/cyclopedia/player_badge.cpp @@ -7,14 +7,15 @@ * Website: https://docs.opentibiabr.com/ */ -#include "player_badge.hpp" +#include "creatures/players/cyclopedia/player_badge.hpp" +#include "account/account.hpp" #include "creatures/players/player.hpp" +#include "enums/account_errors.hpp" +#include "enums/player_cyclopedia.hpp" #include "game/game.hpp" #include "kv/kv.hpp" -#include "enums/account_errors.hpp" - PlayerBadge::PlayerBadge(Player &player) : m_player(player) { } @@ -23,7 +24,7 @@ bool PlayerBadge::hasBadge(uint8_t id) const { return false; } - if (auto it = std::find_if(m_badgesUnlocked.begin(), m_badgesUnlocked.end(), [id](auto badge_it) { + if (auto it = std::ranges::find_if(m_badgesUnlocked, [id](auto badge_it) { return badge_it.first.m_id == id; }); it != m_badgesUnlocked.end()) { @@ -107,17 +108,17 @@ const std::shared_ptr &PlayerBadge::getUnlockedKV() { } // Badge Calculate Functions -bool PlayerBadge::accountAge(uint8_t amount) { +bool PlayerBadge::accountAge(uint8_t amount) const { return std::floor(m_player.getLoyaltyPoints() / 365) >= amount; } -bool PlayerBadge::loyalty(uint8_t amount) { +bool PlayerBadge::loyalty(uint8_t amount) const { return m_player.getLoyaltyPoints() >= amount; } -std::vector> PlayerBadge::getPlayersInfoByAccount(std::shared_ptr acc) const { - auto [accountPlayers, error] = acc->getAccountPlayers(); - if (error != enumToValue(AccountErrors_t::Ok) || accountPlayers.empty()) { +std::vector> PlayerBadge::getPlayersInfoByAccount(const std::shared_ptr &acc) const { + const auto [accountPlayers, error] = acc->getAccountPlayers(); + if (error != AccountErrors_t::Ok || accountPlayers.empty()) { return {}; } @@ -126,7 +127,8 @@ std::vector> PlayerBadge::getPlayersInfoByAccount(std::s if (!namesList.empty()) { namesList += ", "; } - namesList += fmt::format("'{}'", name); + std::string escapedName = g_database().escapeString(name); + namesList += fmt::format("{}", escapedName); } auto query = fmt::format("SELECT name, level, vocation FROM players WHERE name IN ({})", namesList); @@ -145,7 +147,7 @@ std::vector> PlayerBadge::getPlayersInfoByAccount(std::s return players; } -bool PlayerBadge::accountAllLevel(uint8_t amount) { +bool PlayerBadge::accountAllLevel(uint8_t amount) const { auto players = getPlayersInfoByAccount(m_player.getAccount()); uint16_t total = std::accumulate(players.begin(), players.end(), 0, [](uint16_t sum, const std::shared_ptr &player) { return sum + player->getLevel(); @@ -153,14 +155,14 @@ bool PlayerBadge::accountAllLevel(uint8_t amount) { return total >= amount; } -bool PlayerBadge::accountAllVocations(uint8_t amount) { +bool PlayerBadge::accountAllVocations(uint8_t amount) const { auto knight = false; auto paladin = false; auto druid = false; auto sorcerer = false; for (const auto &player : getPlayersInfoByAccount(m_player.getAccount())) { if (player->getLevel() >= amount) { - auto vocationEnum = player->getPlayerVocationEnum(); + const auto &vocationEnum = player->getPlayerVocationEnum(); if (vocationEnum == Vocation_t::VOCATION_KNIGHT_CIP) { knight = true; } else if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { @@ -175,12 +177,12 @@ bool PlayerBadge::accountAllVocations(uint8_t amount) { return knight && paladin && druid && sorcerer; } -bool PlayerBadge::tournamentParticipation(uint8_t skill) { +bool PlayerBadge::tournamentParticipation(uint8_t skill) const { // todo check if is used return false; } -bool PlayerBadge::tournamentPoints(uint8_t race) { +bool PlayerBadge::tournamentPoints(uint8_t race) const { // todo check if is used return false; } diff --git a/src/creatures/players/cyclopedia/player_badge.hpp b/src/creatures/players/cyclopedia/player_badge.hpp index 25eaea0666f..cc8135b41e4 100644 --- a/src/creatures/players/cyclopedia/player_badge.hpp +++ b/src/creatures/players/cyclopedia/player_badge.hpp @@ -9,16 +9,16 @@ #pragma once -#include "enums/player_cyclopedia.hpp" - class Player; class KV; class Account; +enum class CyclopediaBadge_t : uint8_t; + struct Badge { uint8_t m_id = 0; - CyclopediaBadge_t m_type; - std::string m_name; + CyclopediaBadge_t m_type {}; + std::string m_name {}; uint16_t m_amount = 0; Badge() = default; @@ -31,14 +31,12 @@ struct Badge { } }; -namespace std { - template <> - struct hash { - std::size_t operator()(const Badge &b) const { - return hash()(b.m_id); - } - }; -} +template <> +struct std::hash { + std::size_t operator()(const Badge &b) const noexcept { + return hash()(b.m_id); + } +}; class PlayerBadge { public: @@ -51,13 +49,13 @@ class PlayerBadge { const std::shared_ptr &getUnlockedKV(); // Badge Calculate Functions - bool accountAge(uint8_t amount); - bool loyalty(uint8_t amount); - std::vector> getPlayersInfoByAccount(std::shared_ptr acc) const; - bool accountAllLevel(uint8_t amount); - bool accountAllVocations(uint8_t amount); - [[nodiscard]] bool tournamentParticipation(uint8_t skill); - [[nodiscard]] bool tournamentPoints(uint8_t race); + bool accountAge(uint8_t amount) const; + bool loyalty(uint8_t amount) const; + std::vector> getPlayersInfoByAccount(const std::shared_ptr &acc) const; + bool accountAllLevel(uint8_t amount) const; + bool accountAllVocations(uint8_t amount) const; + [[nodiscard]] bool tournamentParticipation(uint8_t skill) const; + [[nodiscard]] bool tournamentPoints(uint8_t race) const; private: // {badge ID, time when it was unlocked} diff --git a/src/creatures/players/cyclopedia/player_cyclopedia.cpp b/src/creatures/players/cyclopedia/player_cyclopedia.cpp index de34e1d8250..980d6897c31 100644 --- a/src/creatures/players/cyclopedia/player_cyclopedia.cpp +++ b/src/creatures/players/cyclopedia/player_cyclopedia.cpp @@ -7,40 +7,40 @@ * Website: https://docs.opentibiabr.com/ */ -#include "player_cyclopedia.hpp" +#include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "database/databasetasks.hpp" #include "creatures/players/player.hpp" +#include "database/databasetasks.hpp" +#include "enums/player_blessings.hpp" +#include "enums/player_cyclopedia.hpp" #include "game/game.hpp" #include "kv/kv.hpp" -#include "enums/player_blessings.hpp" - PlayerCyclopedia::PlayerCyclopedia(Player &player) : m_player(player) { } -Summary PlayerCyclopedia::getSummary() { +Summary PlayerCyclopedia::getSummary() const { return { getAmount(Summary_t::PREY_CARDS), getAmount(Summary_t::INSTANT_REWARDS), getAmount(Summary_t::HIRELINGS) }; } -void PlayerCyclopedia::loadSummaryData() { - DBResult_ptr result = g_database().storeQuery(fmt::format("SELECT COUNT(*) as `count` FROM `player_hirelings` WHERE `player_id` = {}", m_player.getGUID())); - auto kvScoped = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(static_cast(Summary_t::HIRELINGS))); +void PlayerCyclopedia::loadSummaryData() const { + const DBResult_ptr result = g_database().storeQuery(fmt::format("SELECT COUNT(*) as `count` FROM `player_hirelings` WHERE `player_id` = {}", m_player.getGUID())); + const auto kvScoped = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(static_cast(Summary_t::HIRELINGS))); if (result && !kvScoped->get("amount").has_value()) { kvScoped->set("amount", result->getNumber("count")); } } -void PlayerCyclopedia::loadDeathHistory(uint16_t page, uint16_t entriesPerPage) { +void PlayerCyclopedia::loadDeathHistory(uint16_t page, uint16_t entriesPerPage) const { Benchmark bm_check; uint32_t offset = static_cast(page - 1) * entriesPerPage; - auto query = fmt::format("SELECT `time`, `level`, `killed_by`, `mostdamage_by`, (select count(*) FROM `player_deaths` WHERE `player_id` = {}) as `entries` FROM `player_deaths` WHERE `player_id` = {} AND `time` >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY `time` DESC LIMIT {}, {}", m_player.getGUID(), m_player.getGUID(), offset, entriesPerPage); + const auto query = fmt::format("SELECT `time`, `level`, `killed_by`, `mostdamage_by`, (select count(*) FROM `player_deaths` WHERE `player_id` = {}) as `entries` FROM `player_deaths` WHERE `player_id` = {} AND `time` >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY `time` DESC LIMIT {}, {}", m_player.getGUID(), m_player.getGUID(), offset, entriesPerPage); uint32_t playerID = m_player.getID(); - std::function callback = [playerID, page, entriesPerPage](const DBResult_ptr &result, bool) { - std::shared_ptr player = g_game().getPlayerByID(playerID); + const std::function callback = [playerID, page, entriesPerPage](const DBResult_ptr &result, bool) { + const auto &player = g_game().getPlayerByID(playerID); if (!player) { return; } @@ -81,16 +81,16 @@ void PlayerCyclopedia::loadDeathHistory(uint16_t page, uint16_t entriesPerPage) g_logger().debug("Loading death history from the player {} took {} milliseconds.", m_player.getName(), bm_check.duration()); } -void PlayerCyclopedia::loadRecentKills(uint16_t page, uint16_t entriesPerPage) { +void PlayerCyclopedia::loadRecentKills(uint16_t page, uint16_t entriesPerPage) const { Benchmark bm_check; const std::string &escapedName = g_database().escapeString(m_player.getName()); uint32_t offset = static_cast(page - 1) * entriesPerPage; - auto query = fmt::format("SELECT `d`.`time`, `d`.`killed_by`, `d`.`mostdamage_by`, `d`.`unjustified`, `d`.`mostdamage_unjustified`, `p`.`name`, (select count(*) FROM `player_deaths` WHERE ((`killed_by` = {} AND `is_player` = 1) OR (`mostdamage_by` = {} AND `mostdamage_is_player` = 1))) as `entries` FROM `player_deaths` AS `d` INNER JOIN `players` AS `p` ON `d`.`player_id` = `p`.`id` WHERE ((`d`.`killed_by` = {} AND `d`.`is_player` = 1) OR (`d`.`mostdamage_by` = {} AND `d`.`mostdamage_is_player` = 1)) AND `time` >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 70 DAY)) ORDER BY `time` DESC LIMIT {}, {}", escapedName, escapedName, escapedName, escapedName, offset, entriesPerPage); + const auto query = fmt::format("SELECT `d`.`time`, `d`.`killed_by`, `d`.`mostdamage_by`, `d`.`unjustified`, `d`.`mostdamage_unjustified`, `p`.`name`, (select count(*) FROM `player_deaths` WHERE ((`killed_by` = {} AND `is_player` = 1) OR (`mostdamage_by` = {} AND `mostdamage_is_player` = 1))) as `entries` FROM `player_deaths` AS `d` INNER JOIN `players` AS `p` ON `d`.`player_id` = `p`.`id` WHERE ((`d`.`killed_by` = {} AND `d`.`is_player` = 1) OR (`d`.`mostdamage_by` = {} AND `d`.`mostdamage_is_player` = 1)) AND `time` >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 70 DAY)) ORDER BY `time` DESC LIMIT {}, {}", escapedName, escapedName, escapedName, escapedName, offset, entriesPerPage); uint32_t playerID = m_player.getID(); - std::function callback = [playerID, page, entriesPerPage](const DBResult_ptr &result, bool) { - std::shared_ptr player = g_game().getPlayerByID(playerID); + const std::function callback = [playerID, page, entriesPerPage](const DBResult_ptr &result, bool) { + const auto &player = g_game().getPlayerByID(playerID); if (!player) { return; } @@ -133,7 +133,7 @@ void PlayerCyclopedia::loadRecentKills(uint16_t page, uint16_t entriesPerPage) { g_logger().debug("Loading recent kills from the player {} took {} milliseconds.", m_player.getName(), bm_check.duration()); } -void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, const std::string &id) { +void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, const std::string &id) const { switch (type) { case Summary_t::HOUSE_ITEMS: case Summary_t::BLESSINGS: @@ -150,35 +150,35 @@ void PlayerCyclopedia::updateStoreSummary(uint8_t type, uint16_t amount, const s } } -uint16_t PlayerCyclopedia::getAmount(uint8_t type) { - auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->get("amount"); +uint16_t PlayerCyclopedia::getAmount(uint8_t type) const { + const auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->get("amount"); return static_cast(kvScope ? kvScope->getNumber() : 0); } -void PlayerCyclopedia::updateAmount(uint8_t type, uint16_t amount) { - auto oldAmount = getAmount(type); +void PlayerCyclopedia::updateAmount(uint8_t type, uint16_t amount) const { + const auto oldAmount = getAmount(type); m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->set("amount", oldAmount + amount); } std::map PlayerCyclopedia::getResult(uint8_t type) const { - auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type)); + const auto kvScope = m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type)); std::map result; // ID, amount for (const auto &scope : kvScope->keys()) { - size_t pos = scope.find('.'); + const size_t &pos = scope.find('.'); if (pos == std::string::npos) { g_logger().error("[{}] Invalid key format: {}", __FUNCTION__, scope); continue; } std::string id = scope.substr(0, pos); - auto amount = kvScope->scoped(id)->get("amount"); + const auto amount = kvScope->scoped(id)->get("amount"); result.emplace(std::stoll(id), static_cast(amount ? amount->getNumber() : 0)); } return result; } -void PlayerCyclopedia::insertValue(uint8_t type, uint16_t amount, const std::string &id) { +void PlayerCyclopedia::insertValue(uint8_t type, uint16_t amount, const std::string &id) const { auto result = getResult(type); - auto it = result.find(std::stoll(id)); + const auto it = result.find(std::stoll(id)); auto oldAmount = (it != result.end() ? it->second : 0); auto newAmount = oldAmount + amount; m_player.kv()->scoped("summary")->scoped(g_game().getSummaryKeyByType(type))->scoped(id)->set("amount", newAmount); diff --git a/src/creatures/players/cyclopedia/player_cyclopedia.hpp b/src/creatures/players/cyclopedia/player_cyclopedia.hpp index 32c446cc368..0f399af03b2 100644 --- a/src/creatures/players/cyclopedia/player_cyclopedia.hpp +++ b/src/creatures/players/cyclopedia/player_cyclopedia.hpp @@ -9,9 +9,6 @@ #pragma once -#include "creatures/creatures_definitions.hpp" -#include "enums/player_cyclopedia.hpp" - class Player; class KV; @@ -28,18 +25,18 @@ class PlayerCyclopedia { public: explicit PlayerCyclopedia(Player &player); - Summary getSummary(); + Summary getSummary() const; - void loadSummaryData(); - void loadDeathHistory(uint16_t page, uint16_t entriesPerPage); - void loadRecentKills(uint16_t page, uint16_t entriesPerPage); + void loadSummaryData() const; + void loadDeathHistory(uint16_t page, uint16_t entriesPerPage) const; + void loadRecentKills(uint16_t page, uint16_t entriesPerPage) const; - void updateStoreSummary(uint8_t type, uint16_t amount = 1, const std::string &id = ""); - uint16_t getAmount(uint8_t type); - void updateAmount(uint8_t type, uint16_t amount = 1); + void updateStoreSummary(uint8_t type, uint16_t amount = 1, const std::string &id = "") const; + uint16_t getAmount(uint8_t type) const; + void updateAmount(uint8_t type, uint16_t amount = 1) const; [[nodiscard]] std::map getResult(uint8_t type) const; - void insertValue(uint8_t type, uint16_t amount = 1, const std::string &id = ""); + void insertValue(uint8_t type, uint16_t amount = 1, const std::string &id = "") const; private: Player &m_player; diff --git a/src/creatures/players/cyclopedia/player_title.cpp b/src/creatures/players/cyclopedia/player_title.cpp index 38e4e6428d0..089d02f281c 100644 --- a/src/creatures/players/cyclopedia/player_title.cpp +++ b/src/creatures/players/cyclopedia/player_title.cpp @@ -7,11 +7,15 @@ * Website: https://docs.opentibiabr.com/ */ -#include "player_title.hpp" +#include "creatures/players/cyclopedia/player_title.hpp" +#include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/monsters/monsters.hpp" #include "creatures/players/player.hpp" +#include "enums/account_group_type.hpp" #include "game/game.hpp" #include "kv/kv.hpp" +#include "enums/account_group_type.hpp" PlayerTitle::PlayerTitle(Player &player) : m_player(player) { } @@ -21,7 +25,7 @@ bool PlayerTitle::isTitleUnlocked(uint8_t id) const { return false; } - if (auto it = std::find_if(m_titlesUnlocked.begin(), m_titlesUnlocked.end(), [id](auto title_it) { + if (auto it = std::ranges::find_if(m_titlesUnlocked, [id](auto title_it) { return title_it.first.m_id == id; }); it != m_titlesUnlocked.end()) { @@ -63,7 +67,7 @@ void PlayerTitle::remove(const Title &title) { return; } - auto it = std::find_if(m_titlesUnlocked.begin(), m_titlesUnlocked.end(), [id](auto title_it) { + auto it = std::ranges::find_if(m_titlesUnlocked, [id](auto title_it) { return title_it.first.m_id == id; }); @@ -82,21 +86,21 @@ const std::vector> &PlayerTitle::getUnlockedTitles() } uint8_t PlayerTitle::getCurrentTitle() const { - auto title = m_player.kv()->scoped("titles")->get("current-title"); + const auto title = m_player.kv()->scoped("titles")->get("current-title"); return title ? static_cast(title->getNumber()) : 0; } -void PlayerTitle::setCurrentTitle(uint8_t id) { +void PlayerTitle::setCurrentTitle(uint8_t id) const { m_player.kv()->scoped("titles")->set("current-title", id != 0 && isTitleUnlocked(id) ? id : 0); } -std::string PlayerTitle::getCurrentTitleName() { - auto currentTitle = getCurrentTitle(); +std::string PlayerTitle::getCurrentTitleName() const { + const auto currentTitle = getCurrentTitle(); if (currentTitle == 0) { return ""; } - auto title = g_game().getTitleById(currentTitle); + const auto &title = g_game().getTitleById(currentTitle); if (title.m_id == 0) { return ""; } @@ -176,13 +180,13 @@ const std::shared_ptr &PlayerTitle::getUnlockedKV() { } // Title Calculate Functions -bool PlayerTitle::checkGold(uint32_t amount) { +bool PlayerTitle::checkGold(uint32_t amount) const { return m_player.getBankBalance() >= amount; } -bool PlayerTitle::checkMount(uint32_t amount) { +bool PlayerTitle::checkMount(uint32_t amount) const { uint8_t total = 0; - for (const auto &mount : g_game().mounts.getMounts()) { + for (const auto &mount : g_game().mounts->getMounts()) { if (m_player.hasMount(mount)) { total++; } @@ -190,15 +194,15 @@ bool PlayerTitle::checkMount(uint32_t amount) { return total >= amount; } -bool PlayerTitle::checkOutfit(uint32_t amount) { +bool PlayerTitle::checkOutfit(uint32_t amount) const { return m_player.outfits.size() >= amount; } -bool PlayerTitle::checkLevel(uint32_t amount) { +bool PlayerTitle::checkLevel(uint32_t amount) const { return m_player.getLevel() >= amount; } -bool PlayerTitle::checkHighscore(uint8_t skill) { +bool PlayerTitle::checkHighscore(uint8_t skill) const { Database &db = Database::getInstance(); std::string query; std::string fieldCheck = "id"; @@ -226,7 +230,7 @@ bool PlayerTitle::checkHighscore(uint8_t skill) { break; } - DBResult_ptr result = db.storeQuery(query); + const DBResult_ptr result = db.storeQuery(query); if (!result) { return false; } @@ -237,7 +241,7 @@ bool PlayerTitle::checkHighscore(uint8_t skill) { return resultValue == m_player.getGUID(); } -bool PlayerTitle::checkBestiary(const std::string &name, uint16_t race, bool isBoss /* = false*/, uint32_t amount) { +bool PlayerTitle::checkBestiary(const std::string &name, uint16_t race, bool isBoss /* = false*/, uint32_t amount) const { if (race == 0) { if (name == "Executioner") { // todo check if player has unlocked all bestiary @@ -253,23 +257,23 @@ bool PlayerTitle::checkBestiary(const std::string &name, uint16_t race, bool isB return m_player.isCreatureUnlockedOnTaskHunting(g_monsters().getMonsterTypeByRaceId(race, isBoss)); } -bool PlayerTitle::checkLoginStreak(uint32_t amount) { - auto streakKV = m_player.kv()->scoped("daily-reward")->get("streak"); +bool PlayerTitle::checkLoginStreak(uint32_t amount) const { + const auto streakKV = m_player.kv()->scoped("daily-reward")->get("streak"); return streakKV && streakKV.has_value() && static_cast(streakKV->getNumber()) >= amount; } -bool PlayerTitle::checkTask(uint32_t amount) { +bool PlayerTitle::checkTask(uint32_t amount) const { return m_player.getTaskHuntingPoints() >= amount; } -bool PlayerTitle::checkMap(uint32_t amount) { +bool PlayerTitle::checkMap(uint32_t amount) const { // todo cyclopledia return false; } -bool PlayerTitle::checkOther(const std::string &name) { +bool PlayerTitle::checkOther(const std::string &name) const { if (name == "Guild Leader") { - auto rank = m_player.getGuildRank(); + const auto &rank = m_player.getGuildRank(); return rank && rank->level == 3; } else if (name == "Proconsul of Iksupan") { // Win Ancient Aucar Outfits complete so fight with Atab and be teleported to the arena. diff --git a/src/creatures/players/cyclopedia/player_title.hpp b/src/creatures/players/cyclopedia/player_title.hpp index 0530fcc083d..72362424ea2 100644 --- a/src/creatures/players/cyclopedia/player_title.hpp +++ b/src/creatures/players/cyclopedia/player_title.hpp @@ -9,11 +9,9 @@ #pragma once -#include - -#include "creatures/creatures_definitions.hpp" #include "enums/player_cyclopedia.hpp" -#include "enums/account_group_type.hpp" + +enum PlayerSex_t : uint8_t; class Player; class KV; @@ -60,14 +58,12 @@ struct Title { } }; -namespace std { - template <> - struct hash { - std::size_t operator()(const Title &t) const { - return hash<uint8_t>()(t.m_id); - } - }; -} +template <> +struct std::hash<Title> { + std::size_t operator()(const Title &t) const noexcept { + return hash<uint8_t>()(t.m_id); + } +}; class PlayerTitle { public: @@ -78,24 +74,24 @@ class PlayerTitle { void remove(const Title &title); const std::vector<std::pair<Title, uint32_t>> &getUnlockedTitles(); [[nodiscard]] uint8_t getCurrentTitle() const; - void setCurrentTitle(uint8_t id); - std::string getCurrentTitleName(); + void setCurrentTitle(uint8_t id) const; + std::string getCurrentTitleName() const; static const std::string &getNameBySex(PlayerSex_t sex, const std::string &male, const std::string &female); void checkAndUpdateNewTitles(); void loadUnlockedTitles(); const std::shared_ptr<KV> &getUnlockedKV(); // Title Calculate Functions - bool checkGold(uint32_t amount); - bool checkMount(uint32_t amount); - bool checkOutfit(uint32_t amount); - bool checkLevel(uint32_t amount); - bool checkHighscore(uint8_t skill); - bool checkBestiary(const std::string &name, uint16_t race, bool isBoss = false, uint32_t amount = 0); - bool checkLoginStreak(uint32_t amount); - bool checkTask(uint32_t amount); - bool checkMap(uint32_t amount); - bool checkOther(const std::string &name); + bool checkGold(uint32_t amount) const; + bool checkMount(uint32_t amount) const; + bool checkOutfit(uint32_t amount) const; + bool checkLevel(uint32_t amount) const; + bool checkHighscore(uint8_t skill) const; + bool checkBestiary(const std::string &name, uint16_t race, bool isBoss = false, uint32_t amount = 0) const; + bool checkLoginStreak(uint32_t amount) const; + bool checkTask(uint32_t amount) const; + bool checkMap(uint32_t amount) const; + bool checkOther(const std::string &name) const; private: // {title ID, time when it was unlocked} diff --git a/src/creatures/players/grouping/familiars.cpp b/src/creatures/players/grouping/familiars.cpp index 49394714997..66e9b41bc35 100644 --- a/src/creatures/players/grouping/familiars.cpp +++ b/src/creatures/players/grouping/familiars.cpp @@ -8,10 +8,14 @@ */ #include "creatures/players/grouping/familiars.hpp" -#include "lib/di/container.hpp" + #include "config/configmanager.hpp" +#include "lib/di/container.hpp" #include "utils/pugicast.hpp" #include "utils/tools.hpp" +#include <creatures/creatures_definitions.hpp> + +std::vector<std::shared_ptr<Familiar>> familiars[VOCATION_LAST + 1]; Familiars &Familiars::getInstance() { return inject<Familiars>(); @@ -24,23 +28,27 @@ bool Familiars::reload() { return loadFromXml(); } +std::vector<std::shared_ptr<Familiar>> &Familiars::getFamiliars(uint16_t vocation) { + return familiars[vocation]; +} + bool Familiars::loadFromXml() { pugi::xml_document doc; - auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/familiars.xml"; - pugi::xml_parse_result result = doc.load_file(folder.c_str()); + const auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/familiars.xml"; + const pugi::xml_parse_result result = doc.load_file(folder.c_str()); if (!result) { g_logger().error("Failed to load Familiars"); printXMLError(__FUNCTION__, folder, result); return false; } - for (auto familiarsNode : doc.child("familiars").children()) { + for (const auto &familiarsNode : doc.child("familiars").children()) { pugi::xml_attribute attr; - if ((attr = familiarsNode.attribute("enabled")) && !attr.as_bool()) { + if ((attr = familiarsNode.attribute("enabled") && !attr.as_bool())) { continue; } - if (!(attr = familiarsNode.attribute("vocation"))) { + if (!((attr = familiarsNode.attribute("vocation")))) { g_logger().warn("[Familiars::loadFromXml] - Missing familiar vocation."); continue; } @@ -72,7 +80,7 @@ bool Familiars::loadFromXml() { } std::shared_ptr<Familiar> Familiars::getFamiliarByLookType(uint16_t vocation, uint16_t lookType) const { - if (auto it = std::find_if(familiars[vocation].begin(), familiars[vocation].end(), [lookType](auto familiar_it) { + if (auto it = std::ranges::find_if(familiars[vocation], [lookType](const auto &familiar_it) { return familiar_it->lookType == lookType; }); it != familiars[vocation].end()) { diff --git a/src/creatures/players/grouping/familiars.hpp b/src/creatures/players/grouping/familiars.hpp index 9eda7d95ba2..502874747ef 100644 --- a/src/creatures/players/grouping/familiars.hpp +++ b/src/creatures/players/grouping/familiars.hpp @@ -9,9 +9,6 @@ #pragma once -#include "declarations.hpp" -#include "lib/di/container.hpp" - struct FamiliarEntry { constexpr explicit FamiliarEntry(uint16_t initLookType) : lookType(initLookType) { } @@ -38,12 +35,7 @@ class Familiars { bool loadFromXml(); bool reload(); - std::vector<std::shared_ptr<Familiar>> &getFamiliars(uint16_t vocation) { - return familiars[vocation]; - } + std::vector<std::shared_ptr<Familiar>> &getFamiliars(uint16_t vocation); [[nodiscard]] std::shared_ptr<Familiar> getFamiliarByLookType(uint16_t vocation, uint16_t lookType) const; - -private: - std::vector<std::shared_ptr<Familiar>> familiars[VOCATION_LAST + 1]; }; diff --git a/src/creatures/players/grouping/groups.cpp b/src/creatures/players/grouping/groups.cpp index d1a9568cb11..dc2607f46b9 100644 --- a/src/creatures/players/grouping/groups.cpp +++ b/src/creatures/players/grouping/groups.cpp @@ -7,9 +7,10 @@ * Website: https://docs.opentibiabr.com/ */ +#include "creatures/players/grouping/groups.hpp" + #include "config/configmanager.hpp" #include "game/game.hpp" -#include "creatures/players/grouping/groups.hpp" #include "utils/pugicast.hpp" #include "utils/tools.hpp" @@ -18,7 +19,7 @@ namespace ParsePlayerFlagMap { phmap::flat_hash_map<std::string, PlayerFlags_t> initParsePlayerFlagMap() { phmap::flat_hash_map<std::string, PlayerFlags_t> map; // Iterate through all values of the PlayerFlags_t enumeration - for (auto value : magic_enum::enum_values<PlayerFlags_t>()) { + for (const auto &value : magic_enum::enum_values<PlayerFlags_t>()) { // Get the string representation of the current enumeration value std::string name(magic_enum::enum_name(value).data()); // Convert the string to lowercase @@ -48,8 +49,8 @@ bool Groups::reload() { } void parseGroupFlags(Group &group, const pugi::xml_node &groupNode) { - if (pugi::xml_node node = groupNode.child("flags")) { - for (auto flagNode : node.children()) { + if (const pugi::xml_node node = groupNode.child("flags")) { + for (const auto &flagNode : node.children()) { pugi::xml_attribute attr = flagNode.first_attribute(); if (!attr || !attr.as_bool()) { continue; @@ -67,24 +68,24 @@ void parseGroupFlags(Group &group, const pugi::xml_node &groupNode) { bool Groups::load() { pugi::xml_document doc; - auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/groups.xml"; - pugi::xml_parse_result result = doc.load_file(folder.c_str()); + const auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/groups.xml"; + const pugi::xml_parse_result result = doc.load_file(folder.c_str()); if (!result) { printXMLError(__FUNCTION__, folder, result); return false; } - for (auto groupNode : doc.child("groups").children()) { + for (const auto &groupNode : doc.child("groups").children()) { Group group; group.id = pugi::cast<uint32_t>(groupNode.attribute("id").value()); group.name = groupNode.attribute("name").as_string(); group.access = groupNode.attribute("access").as_bool(); group.maxDepotItems = pugi::cast<uint32_t>(groupNode.attribute("maxdepotitems").value()); group.maxVipEntries = pugi::cast<uint32_t>(groupNode.attribute("maxvipentries").value()); - auto flagsInt = static_cast<uint8_t>(groupNode.attribute("flags").as_uint()); + const auto flagsInt = static_cast<uint8_t>(groupNode.attribute("flags").as_uint()); std::bitset<magic_enum::enum_integer(PlayerFlags_t::FlagLast)> flags(flagsInt); for (uint8_t i = 0; i < getFlagNumber(PlayerFlags_t::FlagLast); i++) { - PlayerFlags_t flag = getFlagFromNumber(i); + const PlayerFlags_t flag = getFlagFromNumber(i); group.flags[i] = flags[Groups::getFlagNumber(flag)]; } @@ -98,7 +99,7 @@ bool Groups::load() { } std::shared_ptr<Group> Groups::getGroup(uint16_t id) const { - if (auto it = std::find_if(groups_vector.begin(), groups_vector.end(), [id](auto group_it) { + if (auto it = std::ranges::find_if(groups_vector, [id](auto group_it) { return group_it->id == id; }); it != groups_vector.end()) { @@ -106,3 +107,7 @@ std::shared_ptr<Group> Groups::getGroup(uint16_t id) const { } return nullptr; } + +std::vector<std::shared_ptr<Group>> &Groups::getGroups() { + return groups_vector; +} diff --git a/src/creatures/players/grouping/groups.hpp b/src/creatures/players/grouping/groups.hpp index af319e95772..91328a0e641 100644 --- a/src/creatures/players/grouping/groups.hpp +++ b/src/creatures/players/grouping/groups.hpp @@ -9,7 +9,7 @@ #pragma once -#include "declarations.hpp" +#include "utils/utils_definitions.hpp" struct Group { std::string name; @@ -27,9 +27,7 @@ class Groups { static bool reload(); bool load(); [[nodiscard]] std::shared_ptr<Group> getGroup(uint16_t id) const; - std::vector<std::shared_ptr<Group>> &getGroups() { - return groups_vector; - } + std::vector<std::shared_ptr<Group>> &getGroups(); private: std::vector<std::shared_ptr<Group>> groups_vector; diff --git a/src/creatures/players/grouping/guild.cpp b/src/creatures/players/grouping/guild.cpp index 240593c1047..b00f3a264c1 100644 --- a/src/creatures/players/grouping/guild.cpp +++ b/src/creatures/players/grouping/guild.cpp @@ -8,10 +8,11 @@ */ #include "creatures/players/grouping/guild.hpp" + #include "game/game.hpp" void Guild::addMember(const std::shared_ptr<Player> &player) { - membersOnline.push_back(player); + membersOnline.emplace_back(player); for (const auto &member : getMembersOnline()) { g_game().updatePlayerHelpers(member); } @@ -30,8 +31,8 @@ void Guild::removeMember(const std::shared_ptr<Player> &player) { } } -GuildRank_ptr Guild::getRankById(uint32_t rankId) { - for (auto rank : ranks) { +GuildRank_ptr Guild::getRankById(uint32_t rankId) const { + for (const auto &rank : ranks) { if (rank->id == rankId) { return rank; } @@ -40,7 +41,7 @@ GuildRank_ptr Guild::getRankById(uint32_t rankId) { } GuildRank_ptr Guild::getRankByName(const std::string &guildName) const { - for (auto rank : ranks) { + for (const auto &rank : ranks) { if (rank->name == guildName) { return rank; } @@ -49,7 +50,7 @@ GuildRank_ptr Guild::getRankByName(const std::string &guildName) const { } GuildRank_ptr Guild::getRankByLevel(uint8_t level) const { - for (auto rank : ranks) { + for (const auto &rank : ranks) { if (rank->level == level) { return rank; } diff --git a/src/creatures/players/grouping/guild.hpp b/src/creatures/players/grouping/guild.hpp index 82b0a7367ea..f4c3f605ac6 100644 --- a/src/creatures/players/grouping/guild.hpp +++ b/src/creatures/players/grouping/guild.hpp @@ -24,7 +24,7 @@ struct GuildRank { using GuildRank_ptr = std::shared_ptr<GuildRank>; -class Guild : public Bankable { +class Guild final : public Bankable { public: Guild(uint32_t initId, std::string initName) : name(std::move(initName)), id(initId) { } @@ -72,7 +72,7 @@ class Guild : public Bankable { return ranks; } - GuildRank_ptr getRankById(uint32_t id); + GuildRank_ptr getRankById(uint32_t id) const; GuildRank_ptr getRankByName(const std::string &name) const; GuildRank_ptr getRankByLevel(uint8_t level) const; void addRank(uint32_t id, const std::string &name, uint8_t level); diff --git a/src/creatures/players/grouping/party.cpp b/src/creatures/players/grouping/party.cpp index 3a5d4d78183..e63ca14b629 100644 --- a/src/creatures/players/grouping/party.cpp +++ b/src/creatures/players/grouping/party.cpp @@ -7,15 +7,18 @@ * Website: https://docs.opentibiabr.com/ */ -#include <utility> - #include "creatures/players/grouping/party.hpp" + +#include "config/configmanager.hpp" +#include "creatures/creature.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "lua/creature/events.hpp" +#include "game/movement/position.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/events.hpp" -std::shared_ptr<Party> Party::create(std::shared_ptr<Player> leader) { +std::shared_ptr<Party> Party::create(const std::shared_ptr<Player> &leader) { auto party = std::make_shared<Party>(); party->m_leader = leader; leader->setParty(party); @@ -25,6 +28,39 @@ std::shared_ptr<Party> Party::create(std::shared_ptr<Player> leader) { return party; } +std::shared_ptr<Party> Party::getParty() { + return static_self_cast<Party>(); +} + +std::shared_ptr<Player> Party::getLeader() const { + return m_leader.lock(); +} + +std::vector<std::shared_ptr<Player>> Party::getPlayers() const { + std::vector<std::shared_ptr<Player>> players; + for (auto &member : memberList) { + players.push_back(member); + } + players.push_back(getLeader()); + return players; +} + +std::vector<std::shared_ptr<Player>> Party::getMembers() { + return memberList; +} + +std::vector<std::shared_ptr<Player>> Party::getInvitees() { + return inviteList; +} + +size_t Party::getMemberCount() const { + return memberList.size(); +} + +size_t Party::getInvitationCount() const { + return inviteList.size(); +} + void Party::disband() { if (!g_events().eventPartyOnDisband(getParty())) { return; @@ -34,7 +70,7 @@ void Party::disband() { return; } - auto currentLeader = getLeader(); + const auto ¤tLeader = getLeader(); if (!currentLeader) { return; } @@ -53,7 +89,7 @@ void Party::disband() { } inviteList.clear(); - auto members = getMembers(); + const auto &members = getMembers(); for (const auto &member : members) { member->setParty(nullptr); member->sendClosePrivate(CHANNEL_PARTY); @@ -75,12 +111,12 @@ void Party::disband() { membersData.clear(); } -bool Party::leaveParty(std::shared_ptr<Player> player, bool forceRemove /* = false */) { +bool Party::leaveParty(const std::shared_ptr<Player> &player, bool forceRemove /* = false */) { if (!player) { return false; } - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return false; } @@ -123,7 +159,7 @@ bool Party::leaveParty(std::shared_ptr<Player> player, bool forceRemove /* = fal } // since we already passed the leadership, we remove the player from the list - auto it = std::find(memberList.begin(), memberList.end(), player); + auto it = std::ranges::find(memberList, player); if (it != memberList.end()) { memberList.erase(it); } @@ -162,14 +198,14 @@ bool Party::leaveParty(std::shared_ptr<Player> player, bool forceRemove /* = fal return true; } -bool Party::passPartyLeadership(std::shared_ptr<Player> player) { - auto leader = getLeader(); +bool Party::passPartyLeadership(const std::shared_ptr<Player> &player) { + const auto &leader = getLeader(); if (!leader || !player || leader == player || player->getParty().get() != this) { return false; } // Remove it before to broadcast the message correctly - auto it = std::find(memberList.begin(), memberList.end(), player); + auto it = std::ranges::find(memberList, player); if (it != memberList.end()) { memberList.erase(it); } @@ -178,7 +214,7 @@ bool Party::passPartyLeadership(std::shared_ptr<Player> player) { ss << player->getName() << " is now the leader of the party."; broadcastPartyMessage(MESSAGE_PARTY_MANAGEMENT, ss.str(), true); - auto oldLeader = leader; + const auto &oldLeader = leader; m_leader = player; memberList.insert(memberList.begin(), oldLeader); @@ -204,7 +240,7 @@ bool Party::passPartyLeadership(std::shared_ptr<Player> player) { } bool Party::joinParty(const std::shared_ptr<Player> &player) { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return false; } @@ -217,7 +253,7 @@ bool Party::joinParty(const std::shared_ptr<Player> &player) { return false; } - auto it = std::find(inviteList.begin(), inviteList.end(), player); + auto it = std::ranges::find(inviteList, player); if (it == inviteList.end()) { return false; } @@ -243,7 +279,7 @@ bool Party::joinParty(const std::shared_ptr<Player> &player) { leader->sendPlayerPartyIcons(player); player->sendPlayerPartyIcons(leader); - memberList.push_back(player); + memberList.emplace_back(player); g_game().updatePlayerHelpers(player); @@ -261,12 +297,12 @@ bool Party::joinParty(const std::shared_ptr<Player> &player) { } bool Party::removeInvite(const std::shared_ptr<Player> &player, bool removeFromPlayer /* = true*/) { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return false; } - auto it = std::find(inviteList.begin(), inviteList.end(), player); + auto it = std::ranges::find(inviteList, player); if (it == inviteList.end()) { return false; } @@ -294,7 +330,7 @@ bool Party::removeInvite(const std::shared_ptr<Player> &player, bool removeFromP } void Party::revokeInvitation(const std::shared_ptr<Player> &player) { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return; } @@ -311,7 +347,7 @@ void Party::revokeInvitation(const std::shared_ptr<Player> &player) { } bool Party::invitePlayer(const std::shared_ptr<Player> &player) { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return false; } @@ -331,7 +367,7 @@ bool Party::invitePlayer(const std::shared_ptr<Player> &player) { leader->sendTextMessage(MESSAGE_PARTY_MANAGEMENT, ss.str()); - inviteList.push_back(player); + inviteList.emplace_back(player); for (const auto &member : getMembers()) { g_game().updatePlayerHelpers(member); @@ -351,15 +387,15 @@ bool Party::invitePlayer(const std::shared_ptr<Player> &player) { } bool Party::isPlayerInvited(const std::shared_ptr<Player> &player) const { - return std::find(inviteList.begin(), inviteList.end(), player) != inviteList.end(); + return std::ranges::find(inviteList, player) != inviteList.end(); } void Party::updateAllPartyIcons() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return; } - auto members = getMembers(); + const auto &members = getMembers(); for (const auto &member : members) { for (const auto &otherMember : members) { member->sendPartyCreatureShield(otherMember); @@ -373,7 +409,7 @@ void Party::updateAllPartyIcons() { } void Party::broadcastPartyMessage(MessageClasses msgClass, const std::string &msg, bool sendToInvitations /*= false*/) { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return; } @@ -390,9 +426,13 @@ void Party::broadcastPartyMessage(MessageClasses msgClass, const std::string &ms } } +bool Party::empty() const { + return memberList.empty() && inviteList.empty(); +} + void Party::updateSharedExperience() { if (sharedExpActive) { - bool result = getSharedExperienceStatus() == SHAREDEXP_OK; + const bool result = getSharedExperienceStatus() == SHAREDEXP_OK; if (result != sharedExpEnabled) { sharedExpEnabled = result; updateAllPartyIcons(); @@ -400,7 +440,7 @@ void Party::updateSharedExperience() { } } -const char* Party::getSharedExpReturnMessage(SharedExpStatus_t value) { +const char* Party::getSharedExpReturnMessage(SharedExpStatus_t value) const { switch (value) { case SHAREDEXP_OK: return "Shared Experience is now active."; @@ -417,8 +457,8 @@ const char* Party::getSharedExpReturnMessage(SharedExpStatus_t value) { } } -bool Party::setSharedExperience(std::shared_ptr<Player> player, bool newSharedExpActive, bool silent /*= false*/) { - auto leader = getLeader(); +bool Party::setSharedExperience(const std::shared_ptr<Player> &player, bool newSharedExpActive, bool silent /*= false*/) { + const auto &leader = getLeader(); if (!player || leader != player) { return false; } @@ -430,7 +470,7 @@ bool Party::setSharedExperience(std::shared_ptr<Player> player, bool newSharedEx this->sharedExpActive = newSharedExpActive; if (newSharedExpActive) { - SharedExpStatus_t sharedExpStatus = getSharedExperienceStatus(); + const SharedExpStatus_t &sharedExpStatus = getSharedExperienceStatus(); this->sharedExpEnabled = sharedExpStatus == SHAREDEXP_OK; if (!silent) { leader->sendTextMessage(MESSAGE_PARTY_MANAGEMENT, getSharedExpReturnMessage(sharedExpStatus)); @@ -445,7 +485,15 @@ bool Party::setSharedExperience(std::shared_ptr<Player> player, bool newSharedEx return true; } -void Party::shareExperience(uint64_t experience, std::shared_ptr<Creature> target /* = nullptr*/) { +bool Party::isSharedExperienceActive() const { + return sharedExpActive; +} + +bool Party::isSharedExperienceEnabled() const { + return sharedExpEnabled; +} + +void Party::shareExperience(uint64_t experience, const std::shared_ptr<Creature> &target /* = nullptr*/) { auto leader = getLeader(); if (!leader) { return; @@ -461,12 +509,12 @@ void Party::shareExperience(uint64_t experience, std::shared_ptr<Creature> targe leader->onGainSharedExperience(shareExperience, target); } -bool Party::canUseSharedExperience(std::shared_ptr<Player> player) { - return getMemberSharedExperienceStatus(std::move(player)) == SHAREDEXP_OK; +bool Party::canUseSharedExperience(const std::shared_ptr<Player> &player) { + return getMemberSharedExperienceStatus(player) == SHAREDEXP_OK; } -SharedExpStatus_t Party::getMemberSharedExperienceStatus(std::shared_ptr<Player> player) { - auto leader = getLeader(); +SharedExpStatus_t Party::getMemberSharedExperienceStatus(const std::shared_ptr<Player> &player) { + const auto &leader = getLeader(); if (!leader) { return SHAREDEXP_EMPTYPARTY; } @@ -474,7 +522,7 @@ SharedExpStatus_t Party::getMemberSharedExperienceStatus(std::shared_ptr<Player> return SHAREDEXP_EMPTYPARTY; } - uint32_t minLevel = getMinLevel(); + const uint32_t minLevel = getMinLevel(); if (player->getLevel() < minLevel) { return SHAREDEXP_LEVELDIFFTOOLARGE; } @@ -496,7 +544,7 @@ float Party::shareRangeMultiplier() const { } uint32_t Party::getHighestLevel() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return 0; } @@ -515,7 +563,7 @@ uint32_t Party::getMinLevel() { } uint32_t Party::getLowestLevel() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return 0; } @@ -532,27 +580,27 @@ uint32_t Party::getMaxLevel() { return static_cast<uint32_t>(std::floor(static_cast<float>(getLowestLevel()) * shareRangeMultiplier())); } -bool Party::isPlayerActive(std::shared_ptr<Player> player) { +bool Party::isPlayerActive(const std::shared_ptr<Player> &player) { auto it = ticksMap.find(player->getID()); if (it == ticksMap.end()) { return false; } - uint64_t timeDiff = OTSYS_TIME() - it->second; + const uint64_t timeDiff = OTSYS_TIME() - it->second; return timeDiff <= 2 * 60 * 1000; } SharedExpStatus_t Party::getSharedExperienceStatus() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return SHAREDEXP_EMPTYPARTY; } - SharedExpStatus_t leaderStatus = getMemberSharedExperienceStatus(leader); + const SharedExpStatus_t &leaderStatus = getMemberSharedExperienceStatus(leader); if (leaderStatus != SHAREDEXP_OK) { return leaderStatus; } for (const auto &member : getMembers()) { - SharedExpStatus_t memberStatus = getMemberSharedExperienceStatus(member); + const SharedExpStatus_t &memberStatus = getMemberSharedExperienceStatus(member); if (memberStatus != SHAREDEXP_OK) { return memberStatus; } @@ -560,14 +608,14 @@ SharedExpStatus_t Party::getSharedExperienceStatus() { return SHAREDEXP_OK; } -void Party::updatePlayerTicks(std::shared_ptr<Player> player, uint32_t points) { +void Party::updatePlayerTicks(const std::shared_ptr<Player> &player, uint32_t points) { if (points != 0 && !player->hasFlag(PlayerFlags_t::NotGainInFight)) { ticksMap[player->getID()] = OTSYS_TIME(); updateSharedExperience(); } } -void Party::clearPlayerPoints(std::shared_ptr<Player> player) { +void Party::clearPlayerPoints(const std::shared_ptr<Player> &player) { auto it = ticksMap.find(player->getID()); if (it != ticksMap.end()) { ticksMap.erase(it); @@ -576,18 +624,18 @@ void Party::clearPlayerPoints(std::shared_ptr<Player> player) { } bool Party::canOpenCorpse(uint32_t ownerId) const { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return false; } - if (std::shared_ptr<Player> player = g_game().getPlayerByID(ownerId)) { + if (const auto &player = g_game().getPlayerByID(ownerId)) { return leader->getID() == ownerId || player->getParty().get() == this; } return false; } -void Party::showPlayerStatus(std::shared_ptr<Player> player, std::shared_ptr<Player> member, bool showStatus) { +void Party::showPlayerStatus(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &member, bool showStatus) const { player->sendPartyCreatureShowStatus(member, showStatus); member->sendPartyCreatureShowStatus(player, showStatus); if (showStatus) { @@ -613,22 +661,22 @@ void Party::showPlayerStatus(std::shared_ptr<Player> player, std::shared_ptr<Pla } } -void Party::updatePlayerStatus(std::shared_ptr<Player> player) { - auto leader = getLeader(); +void Party::updatePlayerStatus(const std::shared_ptr<Player> &player) { + const auto &leader = getLeader(); if (!leader) { return; } - int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); + const int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); for (const auto &member : getMembers()) { - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); if (condition) { showPlayerStatus(player, member, true); } else { showPlayerStatus(player, member, false); } } - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); if (condition) { showPlayerStatus(player, leader, true); } else { @@ -636,17 +684,17 @@ void Party::updatePlayerStatus(std::shared_ptr<Player> player) { } } -void Party::updatePlayerStatus(std::shared_ptr<Player> player, const Position &oldPos, const Position &newPos) { - auto leader = getLeader(); +void Party::updatePlayerStatus(const std::shared_ptr<Player> &player, const Position &oldPos, const Position &newPos) { + const auto &leader = getLeader(); if (!leader) { return; } - int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); + const int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); if (maxDistance != 0) { for (const auto &member : getMembers()) { - bool condition1 = (Position::getDistanceX(oldPos, member->getPosition()) <= maxDistance && Position::getDistanceY(oldPos, member->getPosition()) <= maxDistance); - bool condition2 = (Position::getDistanceX(newPos, member->getPosition()) <= maxDistance && Position::getDistanceY(newPos, member->getPosition()) <= maxDistance); + const bool condition1 = Position::getDistanceX(oldPos, member->getPosition()) <= maxDistance && Position::getDistanceY(oldPos, member->getPosition()) <= maxDistance; + const bool condition2 = Position::getDistanceX(newPos, member->getPosition()) <= maxDistance && Position::getDistanceY(newPos, member->getPosition()) <= maxDistance; if (condition1 && !condition2) { showPlayerStatus(player, member, false); } else if (!condition1 && condition2) { @@ -654,8 +702,8 @@ void Party::updatePlayerStatus(std::shared_ptr<Player> player, const Position &o } } - bool condition1 = (Position::getDistanceX(oldPos, leader->getPosition()) <= maxDistance && Position::getDistanceY(oldPos, leader->getPosition()) <= maxDistance); - bool condition2 = (Position::getDistanceX(newPos, leader->getPosition()) <= maxDistance && Position::getDistanceY(newPos, leader->getPosition()) <= maxDistance); + const bool condition1 = Position::getDistanceX(oldPos, leader->getPosition()) <= maxDistance && Position::getDistanceY(oldPos, leader->getPosition()) <= maxDistance; + const bool condition2 = Position::getDistanceX(newPos, leader->getPosition()) <= maxDistance && Position::getDistanceY(newPos, leader->getPosition()) <= maxDistance; if (condition1 && !condition2) { showPlayerStatus(player, leader, false); } else if (!condition1 && condition2) { @@ -664,68 +712,68 @@ void Party::updatePlayerStatus(std::shared_ptr<Player> player, const Position &o } } -void Party::updatePlayerHealth(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint8_t healthPercent) { - auto leader = getLeader(); +void Party::updatePlayerHealth(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint8_t healthPercent) { + const auto &leader = getLeader(); if (!leader) { return; } - int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); - auto playerPosition = player->getPosition(); - auto leaderPosition = leader->getPosition(); + const int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); + const auto playerPosition = player->getPosition(); + const auto leaderPosition = leader->getPosition(); for (const auto &member : getMembers()) { auto memberPosition = member->getPosition(); - bool condition = (maxDistance == 0 || (Position::getDistanceX(playerPosition, memberPosition) <= maxDistance && Position::getDistanceY(playerPosition, memberPosition) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(playerPosition, memberPosition) <= maxDistance && Position::getDistanceY(playerPosition, memberPosition) <= maxDistance)); if (condition) { member->sendPartyCreatureHealth(target, healthPercent); } } - bool condition = (maxDistance == 0 || (Position::getDistanceX(playerPosition, leaderPosition) <= maxDistance && Position::getDistanceY(playerPosition, leaderPosition) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(playerPosition, leaderPosition) <= maxDistance && Position::getDistanceY(playerPosition, leaderPosition) <= maxDistance)); if (condition) { leader->sendPartyCreatureHealth(target, healthPercent); } } -void Party::updatePlayerMana(std::shared_ptr<Player> player, uint8_t manaPercent) { - auto leader = getLeader(); +void Party::updatePlayerMana(const std::shared_ptr<Player> &player, uint8_t manaPercent) { + const auto &leader = getLeader(); if (!leader) { return; } - int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); + const int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); for (const auto &member : getMembers()) { - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); if (condition) { member->sendPartyPlayerMana(player, manaPercent); } } - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); if (condition) { leader->sendPartyPlayerMana(player, manaPercent); } } -void Party::updatePlayerVocation(std::shared_ptr<Player> player) { - auto leader = getLeader(); +void Party::updatePlayerVocation(const std::shared_ptr<Player> &player) { + const auto &leader = getLeader(); if (!leader) { return; } - int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); + const int32_t maxDistance = g_configManager().getNumber(PARTY_LIST_MAX_DISTANCE); for (const auto &member : getMembers()) { - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), member->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), member->getPosition()) <= maxDistance)); if (condition) { member->sendPartyPlayerVocation(player); } } - bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); + const bool condition = (maxDistance == 0 || (Position::getDistanceX(player->getPosition(), leader->getPosition()) <= maxDistance && Position::getDistanceY(player->getPosition(), leader->getPosition()) <= maxDistance)); if (condition) { leader->sendPartyPlayerVocation(player); } } void Party::updateTrackerAnalyzer() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return; } @@ -737,21 +785,21 @@ void Party::updateTrackerAnalyzer() { leader->updatePartyTrackerAnalyzer(); } -void Party::addPlayerLoot(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { - auto leader = getLeader(); +void Party::addPlayerLoot(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { + const auto &leader = getLeader(); if (!leader) { return; } - auto playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); + std::shared_ptr<PartyAnalyzer> playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); if (!playerAnalyzer) { playerAnalyzer = std::make_shared<PartyAnalyzer>(player->getID(), player->getName()); - membersData.push_back(playerAnalyzer); + membersData.emplace_back(playerAnalyzer); } uint32_t count = std::max<uint32_t>(1, item->getItemCount()); if (auto it = playerAnalyzer->lootMap.find(item->getID()); it != playerAnalyzer->lootMap.end()) { - (*it).second += count; + it->second += count; } else { playerAnalyzer->lootMap.insert({ item->getID(), count }); } @@ -759,14 +807,14 @@ void Party::addPlayerLoot(std::shared_ptr<Player> player, std::shared_ptr<Item> if (priceType == LEADER_PRICE) { playerAnalyzer->lootPrice += leader->getItemCustomPrice(item->getID()) * count; } else { - std::map<uint16_t, uint64_t> itemMap { { item->getID(), count } }; + const std::map<uint16_t, uint64_t> itemMap { { item->getID(), count } }; playerAnalyzer->lootPrice += g_game().getItemMarketPrice(itemMap, false); } updateTrackerAnalyzer(); } -void Party::addPlayerSupply(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { - auto leader = getLeader(); +void Party::addPlayerSupply(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { + const auto &leader = getLeader(); if (!leader) { return; } @@ -774,11 +822,11 @@ void Party::addPlayerSupply(std::shared_ptr<Player> player, std::shared_ptr<Item std::shared_ptr<PartyAnalyzer> playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); if (!playerAnalyzer) { playerAnalyzer = std::make_shared<PartyAnalyzer>(player->getID(), player->getName()); - membersData.push_back(playerAnalyzer); + membersData.emplace_back(playerAnalyzer); } if (auto it = playerAnalyzer->supplyMap.find(item->getID()); it != playerAnalyzer->supplyMap.end()) { - (*it).second += 1; + it->second += 1; } else { playerAnalyzer->supplyMap.insert({ item->getID(), 1 }); } @@ -786,28 +834,28 @@ void Party::addPlayerSupply(std::shared_ptr<Player> player, std::shared_ptr<Item if (priceType == LEADER_PRICE) { playerAnalyzer->supplyPrice += leader->getItemCustomPrice(item->getID(), true); } else { - std::map<uint16_t, uint64_t> itemMap { { item->getID(), 1 } }; + const std::map<uint16_t, uint64_t> itemMap { { item->getID(), 1 } }; playerAnalyzer->supplyPrice += g_game().getItemMarketPrice(itemMap, true); } updateTrackerAnalyzer(); } -void Party::addPlayerDamage(std::shared_ptr<Player> player, uint64_t amount) { - auto playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); +void Party::addPlayerDamage(const std::shared_ptr<Player> &player, uint64_t amount) { + std::shared_ptr<PartyAnalyzer> playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); if (!playerAnalyzer) { playerAnalyzer = std::make_shared<PartyAnalyzer>(player->getID(), player->getName()); - membersData.push_back(playerAnalyzer); + membersData.emplace_back(playerAnalyzer); } playerAnalyzer->damage += amount; updateTrackerAnalyzer(); } -void Party::addPlayerHealing(std::shared_ptr<Player> player, uint64_t amount) { - auto playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); +void Party::addPlayerHealing(const std::shared_ptr<Player> &player, uint64_t amount) { + std::shared_ptr<PartyAnalyzer> playerAnalyzer = getPlayerPartyAnalyzerStruct(player->getID()); if (!playerAnalyzer) { playerAnalyzer = std::make_shared<PartyAnalyzer>(player->getID(), player->getName()); - membersData.push_back(playerAnalyzer); + membersData.emplace_back(playerAnalyzer); } playerAnalyzer->healing += amount; @@ -815,7 +863,7 @@ void Party::addPlayerHealing(std::shared_ptr<Player> player, uint64_t amount) { } void Party::switchAnalyzerPriceType() { - auto leader = getLeader(); + const auto &leader = getLeader(); if (!leader) { return; } @@ -831,8 +879,8 @@ void Party::resetAnalyzer() { updateTrackerAnalyzer(); } -void Party::reloadPrices() { - auto leader = getLeader(); +void Party::reloadPrices() const { + const auto &leader = getLeader(); if (!leader) { return; } @@ -845,13 +893,28 @@ void Party::reloadPrices() { } analyzer->lootPrice = 0; - for (const auto it : analyzer->lootMap) { - analyzer->lootPrice += leader->getItemCustomPrice(it.first) * it.second; + for (const auto &[itemId, price] : analyzer->lootMap) { + analyzer->lootPrice += leader->getItemCustomPrice(itemId) * price; } analyzer->supplyPrice = 0; - for (const auto it : analyzer->supplyMap) { - analyzer->supplyPrice += leader->getItemCustomPrice(it.first, true) * it.second; + for (const auto &[itemId, price] : analyzer->supplyMap) { + analyzer->supplyPrice += leader->getItemCustomPrice(itemId, true) * price; } } } + +std::shared_ptr<PartyAnalyzer> Party::getPlayerPartyAnalyzerStruct(uint32_t playerId) const { + if (auto it = std::ranges::find_if(membersData, [playerId](const std::shared_ptr<PartyAnalyzer> &preyIt) { + return preyIt->id == playerId; + }); + it != membersData.end()) { + return *it; + } + + return nullptr; +} + +uint32_t Party::getAnalyzerTimeNow() const { + return static_cast<uint32_t>(time(nullptr) - trackerTime); +} diff --git a/src/creatures/players/grouping/party.hpp b/src/creatures/players/grouping/party.hpp index c8bc9b6a653..cef450c0c77 100644 --- a/src/creatures/players/grouping/party.hpp +++ b/src/creatures/players/grouping/party.hpp @@ -9,9 +9,9 @@ #pragma once -#include "creatures/players/player.hpp" -#include "creatures/monsters/monsters.hpp" -#include "lib/di/container.hpp" +#include "creatures/creatures_definitions.hpp" + +enum MessageClasses : uint8_t; enum SharedExpStatus_t : uint8_t { SHAREDEXP_OK, @@ -21,103 +21,71 @@ enum SharedExpStatus_t : uint8_t { SHAREDEXP_EMPTYPARTY }; +struct Position; + class Player; class Party; +class Item; +class Creature; -class Party : public SharedObject { +class Party final : public SharedObject { public: - static std::shared_ptr<Party> create(std::shared_ptr<Player> leader); - - std::shared_ptr<Party> getParty() { - return static_self_cast<Party>(); - } - - std::shared_ptr<Player> getLeader() const { - return m_leader.lock(); - } - std::vector<std::shared_ptr<Player>> getPlayers() const { - std::vector<std::shared_ptr<Player>> players; - for (auto &member : memberList) { - players.push_back(member); - } - players.push_back(getLeader()); - return players; - } - std::vector<std::shared_ptr<Player>> getMembers() { - return memberList; - } - std::vector<std::shared_ptr<Player>> getInvitees() { - return inviteList; - } - size_t getMemberCount() const { - return memberList.size(); - } - size_t getInvitationCount() const { - return inviteList.size(); - } + static std::shared_ptr<Party> create(const std::shared_ptr<Player> &leader); + + std::shared_ptr<Party> getParty(); + + std::shared_ptr<Player> getLeader() const; + std::vector<std::shared_ptr<Player>> getPlayers() const; + std::vector<std::shared_ptr<Player>> getMembers(); + std::vector<std::shared_ptr<Player>> getInvitees(); + size_t getMemberCount() const; + size_t getInvitationCount() const; void disband(); bool invitePlayer(const std::shared_ptr<Player> &player); bool joinParty(const std::shared_ptr<Player> &player); void revokeInvitation(const std::shared_ptr<Player> &player); - bool passPartyLeadership(std::shared_ptr<Player> player); - bool leaveParty(std::shared_ptr<Player> player, bool forceRemove = false); + bool passPartyLeadership(const std::shared_ptr<Player> &player); + bool leaveParty(const std::shared_ptr<Player> &player, bool forceRemove = false); bool removeInvite(const std::shared_ptr<Player> &player, bool removeFromPlayer = true); bool isPlayerInvited(const std::shared_ptr<Player> &player) const; void updateAllPartyIcons(); void broadcastPartyMessage(MessageClasses msgClass, const std::string &msg, bool sendToInvitations = false); - bool empty() const { - return memberList.empty() && inviteList.empty(); - } + bool empty() const; bool canOpenCorpse(uint32_t ownerId) const; - void shareExperience(uint64_t experience, std::shared_ptr<Creature> target = nullptr); - bool setSharedExperience(std::shared_ptr<Player> player, bool sharedExpActive, bool silent = false); - bool isSharedExperienceActive() const { - return sharedExpActive; - } - bool isSharedExperienceEnabled() const { - return sharedExpEnabled; - } - bool canUseSharedExperience(std::shared_ptr<Player> player); - SharedExpStatus_t getMemberSharedExperienceStatus(std::shared_ptr<Player> player); + void shareExperience(uint64_t experience, const std::shared_ptr<Creature> &target = nullptr); + bool setSharedExperience(const std::shared_ptr<Player> &player, bool sharedExpActive, bool silent = false); + bool isSharedExperienceActive() const; + bool isSharedExperienceEnabled() const; + bool canUseSharedExperience(const std::shared_ptr<Player> &player); + SharedExpStatus_t getMemberSharedExperienceStatus(const std::shared_ptr<Player> &player); void updateSharedExperience(); - void updatePlayerTicks(std::shared_ptr<Player> player, uint32_t points); - void clearPlayerPoints(std::shared_ptr<Player> player); + void updatePlayerTicks(const std::shared_ptr<Player> &player, uint32_t points); + void clearPlayerPoints(const std::shared_ptr<Player> &player); - void showPlayerStatus(std::shared_ptr<Player> player, std::shared_ptr<Player> member, bool showStatus); - void updatePlayerStatus(std::shared_ptr<Player> player); - void updatePlayerStatus(std::shared_ptr<Player> player, const Position &oldPos, const Position &newPos); - void updatePlayerHealth(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint8_t healthPercent); - void updatePlayerMana(std::shared_ptr<Player> player, uint8_t manaPercent); - void updatePlayerVocation(std::shared_ptr<Player> player); + void showPlayerStatus(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &member, bool showStatus) const; + void updatePlayerStatus(const std::shared_ptr<Player> &player); + void updatePlayerStatus(const std::shared_ptr<Player> &player, const Position &oldPos, const Position &newPos); + void updatePlayerHealth(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint8_t healthPercent); + void updatePlayerMana(const std::shared_ptr<Player> &player, uint8_t manaPercent); + void updatePlayerVocation(const std::shared_ptr<Player> &player); void updateTrackerAnalyzer(); - void addPlayerLoot(std::shared_ptr<Player> player, std::shared_ptr<Item> item); - void addPlayerSupply(std::shared_ptr<Player> player, std::shared_ptr<Item> item); - void addPlayerDamage(std::shared_ptr<Player> player, uint64_t amount); - void addPlayerHealing(std::shared_ptr<Player> player, uint64_t amount); + void addPlayerLoot(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item); + void addPlayerSupply(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item); + void addPlayerDamage(const std::shared_ptr<Player> &player, uint64_t amount); + void addPlayerHealing(const std::shared_ptr<Player> &player, uint64_t amount); void switchAnalyzerPriceType(); void resetAnalyzer(); - void reloadPrices(); - - std::shared_ptr<PartyAnalyzer> getPlayerPartyAnalyzerStruct(uint32_t playerId) const { - if (auto it = std::find_if(membersData.begin(), membersData.end(), [playerId](const std::shared_ptr<PartyAnalyzer> &preyIt) { - return preyIt->id == playerId; - }); - it != membersData.end()) { - return *it; - } + void reloadPrices() const; - return nullptr; - } + std::shared_ptr<PartyAnalyzer> getPlayerPartyAnalyzerStruct(uint32_t playerId) const; - uint32_t getAnalyzerTimeNow() const { - return static_cast<uint32_t>(time(nullptr) - trackerTime); - } + uint32_t getAnalyzerTimeNow() const; public: // Party analyzer @@ -126,8 +94,8 @@ class Party : public SharedObject { std::vector<std::shared_ptr<PartyAnalyzer>> membersData; private: - const char* getSharedExpReturnMessage(SharedExpStatus_t value); - bool isPlayerActive(std::shared_ptr<Player> player); + const char* getSharedExpReturnMessage(SharedExpStatus_t value) const; + bool isPlayerActive(const std::shared_ptr<Player> &player); SharedExpStatus_t getSharedExperienceStatus(); uint32_t getHighestLevel(); uint32_t getLowestLevel(); diff --git a/src/creatures/players/grouping/team_finder.hpp b/src/creatures/players/grouping/team_finder.hpp index 9fafbd03227..e46217560b6 100644 --- a/src/creatures/players/grouping/team_finder.hpp +++ b/src/creatures/players/grouping/team_finder.hpp @@ -1,5 +1,3 @@ -#include <utility> - /** * Canary - A free and open-source MMORPG server emulator * Copyright (©) 2019-2024 OpenTibiaBR <opentibiabr@outlook.com> @@ -16,7 +14,7 @@ * This class is responsible control and manage the team finder feature. **/ -class TeamFinder { +class TeamFinder final { public: TeamFinder() = default; TeamFinder(uint16_t initMinLevel, uint16_t initMaxLevel, uint8_t initVocationIDs, uint16_t initTeamSlots, uint16_t initFreeSlots, bool initPartyBool, uint32_t initTimestamp, uint8_t initTeamType, uint16_t initBossID, uint16_t initHunt_type, uint16_t initHunt_area, uint16_t initQuestID, uint32_t initLeaderGuid, std::map<uint32_t, uint8_t> initMembersMap) : @@ -34,7 +32,7 @@ class TeamFinder { questID(initQuestID), leaderGuid(initLeaderGuid), membersMap(std::move(initMembersMap)) { } - virtual ~TeamFinder() = default; + ~TeamFinder() = default; uint16_t minLevel = 0; uint16_t maxLevel = 0; diff --git a/src/creatures/players/imbuements/imbuements.cpp b/src/creatures/players/imbuements/imbuements.cpp index 06db26b7210..c71a56fd588 100644 --- a/src/creatures/players/imbuements/imbuements.cpp +++ b/src/creatures/players/imbuements/imbuements.cpp @@ -8,8 +8,17 @@ */ #include "creatures/players/imbuements/imbuements.hpp" -#include "lua/creature/events.hpp" + +#include "config/configmanager.hpp" +#include "creatures/players/player.hpp" +#include "items/item.hpp" +#include "lib/di/container.hpp" #include "utils/pugicast.hpp" +#include <utils/tools.hpp> + +Imbuements &Imbuements::getInstance() { + return inject<Imbuements>(); +} Imbuement* Imbuements::getImbuement(uint16_t id) { if (id == 0) { @@ -34,7 +43,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { } loaded = true; - for (auto baseNode : doc.child("imbuements").children()) { + for (const auto &baseNode : doc.child("imbuements").children()) { pugi::xml_attribute attr; // Base for imbue if (strcasecmp(baseNode.name(), "base") == 0) { @@ -82,14 +91,14 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - auto imbuements = imbuementMap.emplace(std::piecewise_construct, std::forward_as_tuple(runningid), std::forward_as_tuple(runningid, baseid)); + auto [imbuementInfo, inserted] = imbuementMap.emplace(std::piecewise_construct, std::forward_as_tuple(runningid), std::forward_as_tuple(runningid, baseid)); - if (!imbuements.second) { + if (!inserted) { g_logger().warn("Duplicate imbuement of Base ID: '{}' ignored", baseid); continue; } - Imbuement &imbuement = imbuements.first->second; + Imbuement &imbuement = imbuementInfo->second; pugi::xml_attribute iconBase = baseNode.attribute("iconid"); if (!iconBase) { @@ -122,7 +131,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - uint16_t category = pugi::cast<uint16_t>(categorybase.value()); + auto category = pugi::cast<uint16_t>(categorybase.value()); auto category_p = getCategoryByID(category); if (category_p == nullptr) { g_logger().warn("Category imbuement {} not exist", category); @@ -138,26 +147,26 @@ bool Imbuements::loadFromXml(bool /* reloading */) { } imbuement.name = nameBase.value(); - for (auto childNode : baseNode.children()) { - if (!(attr = childNode.attribute("key"))) { + for (const auto &childNode : baseNode.children()) { + if (!((attr = childNode.attribute("key")))) { g_logger().warn("Missing key attribute in imbuement id: {}", runningid); continue; } std::string type = attr.as_string(); if (strcasecmp(type.c_str(), "item") == 0) { - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing item ID for imbuement name '{}'", imbuement.name); continue; } - uint16_t sourceId = pugi::cast<uint16_t>(attr.value()); + auto sourceId = pugi::cast<uint16_t>(attr.value()); uint16_t count = 1; if ((attr = childNode.attribute("count"))) { count = pugi::cast<uint16_t>(childNode.attribute("count").value()); } - auto it2 = std::find_if(imbuement.items.begin(), imbuement.items.end(), [sourceId](const std::pair<uint16_t, uint16_t> &source) -> bool { + const auto &it2 = std::ranges::find_if(imbuement.items, [sourceId](const std::pair<uint16_t, uint16_t> &source) -> bool { return source.first == sourceId; }); @@ -177,7 +186,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { imbuement.description = description; } else if (strcasecmp(type.c_str(), "effect") == 0) { // Effects - if (!(attr = childNode.attribute("type"))) { + if (!((attr = childNode.attribute("type")))) { g_logger().warn("Missing effect type for imbuement name: {}", imbuement.name); continue; } @@ -185,7 +194,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { std::string effecttype = attr.as_string(); if (strcasecmp(effecttype.c_str(), "skill") == 0) { - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing effect value for imbuement name {}", imbuement.name); continue; } @@ -225,11 +234,11 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - if (!(attr = childNode.attribute("bonus"))) { + if (!((attr = childNode.attribute("bonus")))) { g_logger().warn("Missing skill bonus for imbuement name {}", imbuement.name); continue; } - int32_t bonus = pugi::cast<int32_t>(attr.value()); + auto bonus = pugi::cast<int32_t>(attr.value()); if (usenormalskill == 1) { imbuement.skills[skillId] = bonus; @@ -245,7 +254,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { imbuement.skills[skillId - 1] = chance; } } else if (strcasecmp(effecttype.c_str(), "damage") == 0) { - if (!(attr = childNode.attribute("combat"))) { + if (!((attr = childNode.attribute("combat")))) { g_logger().warn("Missing combat for imbuement name {}", imbuement.name); continue; } @@ -256,7 +265,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement.name); continue; } @@ -266,7 +275,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { imbuement.combatType = combatType; imbuement.elementDamage = std::min<int16_t>(100, percent); } else if (strcasecmp(effecttype.c_str(), "reduction") == 0) { - if (!(attr = childNode.attribute("combat"))) { + if (!((attr = childNode.attribute("combat")))) { g_logger().warn("Missing combat for imbuement name {}", imbuement.name); continue; } @@ -277,7 +286,7 @@ bool Imbuements::loadFromXml(bool /* reloading */) { continue; } - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement.name); continue; } @@ -286,14 +295,14 @@ bool Imbuements::loadFromXml(bool /* reloading */) { imbuement.absorbPercent[combatTypeToIndex(combatType)] = percent; } else if (strcasecmp(effecttype.c_str(), "speed") == 0) { - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing speed value for imbuement name {}", imbuement.name); continue; } imbuement.speed = pugi::cast<uint32_t>(attr.value()); } else if (strcasecmp(effecttype.c_str(), "capacity") == 0) { - if (!(attr = childNode.attribute("value"))) { + if (!((attr = childNode.attribute("value")))) { g_logger().warn("Missing cap value for imbuement name {}", imbuement.name); continue; } @@ -320,7 +329,7 @@ bool Imbuements::reload() { } BaseImbuement* Imbuements::getBaseByID(uint16_t id) { - auto baseImbuements = std::find_if(basesImbuement.begin(), basesImbuement.end(), [id](const BaseImbuement &groupImbuement) { + const auto &baseImbuements = std::ranges::find_if(basesImbuement, [id](const BaseImbuement &groupImbuement) { return groupImbuement.id == id; }); @@ -328,14 +337,14 @@ BaseImbuement* Imbuements::getBaseByID(uint16_t id) { } CategoryImbuement* Imbuements::getCategoryByID(uint16_t id) { - auto categoryImbuements = std::find_if(categoriesImbuement.begin(), categoriesImbuement.end(), [id](const CategoryImbuement &categoryImbuement) { + const auto &categoryImbuements = std::ranges::find_if(categoriesImbuement, [id](const CategoryImbuement &categoryImbuement) { return categoryImbuement.id == id; }); return categoryImbuements != categoriesImbuement.end() ? &*categoryImbuements : nullptr; } -std::vector<Imbuement*> Imbuements::getImbuements(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { +std::vector<Imbuement*> Imbuements::getImbuements(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { std::vector<Imbuement*> imbuements; for (auto &[key, value] : imbuementMap) { @@ -363,8 +372,48 @@ std::vector<Imbuement*> Imbuements::getImbuements(std::shared_ptr<Player> player continue; } - imbuements.push_back(imbuement); + imbuements.emplace_back(imbuement); } return imbuements; } + +uint16_t Imbuement::getID() const { + return id; +} + +uint16_t Imbuement::getBaseID() const { + return baseid; +} + +uint32_t Imbuement::getStorage() const { + return storage; +} + +bool Imbuement::isPremium() const { + return premium; +} + +std::string Imbuement::getName() const { + return name; +} + +std::string Imbuement::getDescription() const { + return description; +} + +std::string Imbuement::getSubGroup() const { + return subgroup; +} + +uint16_t Imbuement::getCategory() const { + return category; +} + +const std::vector<std::pair<uint16_t, uint16_t>> &Imbuement::getItems() const { + return items; +} + +uint16_t Imbuement::getIconID() const { + return icon + (baseid - 1); +} diff --git a/src/creatures/players/imbuements/imbuements.hpp b/src/creatures/players/imbuements/imbuements.hpp index 265e813aa1c..b2429cc8137 100644 --- a/src/creatures/players/imbuements/imbuements.hpp +++ b/src/creatures/players/imbuements/imbuements.hpp @@ -9,16 +9,15 @@ #pragma once -#include "creatures/players/player.hpp" -#include "declarations.hpp" -#include "lib/di/container.hpp" -#include "utils/tools.hpp" +#include "creatures/creatures_definitions.hpp" class Player; class Item; class Imbuement; +constexpr int32_t maxSkillOrStatId = std::max<int32_t>(STAT_LAST, SKILL_LAST); + struct BaseImbuement { BaseImbuement(uint16_t initId, std::string initName, uint32_t initPrice, uint32_t initProtectionPrice, uint32_t initRemoveCost, uint32_t initDuration, uint8_t initPercent) : id(initId), name(std::move(initName)), price(initPrice), protectionPrice(initProtectionPrice), removeCost(initRemoveCost), duration(initDuration), percent(initPercent) { } @@ -52,15 +51,13 @@ class Imbuements { Imbuements(const Imbuements &) = delete; Imbuements &operator=(const Imbuements &) = delete; - static Imbuements &getInstance() { - return inject<Imbuements>(); - } + static Imbuements &getInstance(); Imbuement* getImbuement(uint16_t id); BaseImbuement* getBaseByID(uint16_t id); CategoryImbuement* getCategoryByID(uint16_t id); - std::vector<Imbuement*> getImbuements(std::shared_ptr<Player> player, std::shared_ptr<Item> item); + std::vector<Imbuement*> getImbuements(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item); protected: friend class Imbuement; @@ -82,46 +79,26 @@ class Imbuement { Imbuement(uint16_t initId, uint16_t initBaseId) : id(initId), baseid(initBaseId) { } - uint16_t getID() const { - return id; - } + uint16_t getID() const; - uint16_t getBaseID() const { - return baseid; - } + uint16_t getBaseID() const; - uint32_t getStorage() const { - return storage; - } + uint32_t getStorage() const; - bool isPremium() { - return premium; - } - std::string getName() const { - return name; - } - std::string getDescription() const { - return description; - } + bool isPremium() const; + std::string getName() const; + std::string getDescription() const; - std::string getSubGroup() const { - return subgroup; - } + std::string getSubGroup() const; - uint16_t getCategory() const { - return category; - } + uint16_t getCategory() const; - const std::vector<std::pair<uint16_t, uint16_t>> &getItems() const { - return items; - } + const std::vector<std::pair<uint16_t, uint16_t>> &getItems() const; - uint16_t getIconID() { - return icon + (baseid - 1); - } + uint16_t getIconID() const; uint16_t icon = 1; - int32_t stats[STAT_LAST + 1] = {}; + int32_t stats[maxSkillOrStatId + 1] = {}; int32_t skills[SKILL_LAST + 1] = {}; int32_t speed = 0; uint32_t capacity = 0; @@ -136,10 +113,14 @@ class Imbuement { friend class Item; private: - bool premium = false; - uint32_t storage = 0; - uint16_t id, baseid, category = 0; - std::string name, description, subgroup = ""; + bool premium {}; + uint32_t storage {}; + uint16_t id {}; + uint16_t baseid {}; + uint16_t category {}; + std::string name; + std::string description; + std::string subgroup; std::vector<std::pair<uint16_t, uint16_t>> items; }; diff --git a/src/creatures/players/management/ban.cpp b/src/creatures/players/management/ban.cpp index 748b784a77a..8ed990af72c 100644 --- a/src/creatures/players/management/ban.cpp +++ b/src/creatures/players/management/ban.cpp @@ -8,6 +8,7 @@ */ #include "creatures/players/management/ban.hpp" + #include "database/database.hpp" #include "database/databasetasks.hpp" #include "utils/tools.hpp" @@ -15,7 +16,7 @@ bool Ban::acceptConnection(uint32_t clientIP) { std::scoped_lock<std::recursive_mutex> lockClass(lock); - uint64_t currentTime = OTSYS_TIME(); + const uint64_t currentTime = OTSYS_TIME(); auto it = ipConnectMap.find(clientIP); if (it == ipConnectMap.end()) { @@ -29,7 +30,7 @@ bool Ban::acceptConnection(uint32_t clientIP) { return false; } - int64_t timeDiff = currentTime - connectBlock.lastAttempt; + const int64_t timeDiff = currentTime - connectBlock.lastAttempt; connectBlock.lastAttempt = currentTime; if (timeDiff <= 5000) { if (++connectBlock.count > 5) { @@ -51,12 +52,12 @@ bool IOBan::isAccountBanned(uint32_t accountId, BanInfo &banInfo) { std::ostringstream query; query << "SELECT `reason`, `expires_at`, `banned_at`, `banned_by`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `account_bans` WHERE `account_id` = " << accountId; - DBResult_ptr result = db.storeQuery(query.str()); + const DBResult_ptr result = db.storeQuery(query.str()); if (!result) { return false; } - int64_t expiresAt = result->getNumber<int64_t>("expires_at"); + const auto expiresAt = result->getNumber<int64_t>("expires_at"); if (expiresAt != 0 && time(nullptr) > expiresAt) { // Move the ban to history if it has expired query.str(std::string()); @@ -85,12 +86,12 @@ bool IOBan::isIpBanned(uint32_t clientIP, BanInfo &banInfo) { std::ostringstream query; query << "SELECT `reason`, `expires_at`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `ip_bans` WHERE `ip` = " << clientIP; - DBResult_ptr result = db.storeQuery(query.str()); + const DBResult_ptr result = db.storeQuery(query.str()); if (!result) { return false; } - int64_t expiresAt = result->getNumber<int64_t>("expires_at"); + const auto expiresAt = result->getNumber<int64_t>("expires_at"); if (expiresAt != 0 && time(nullptr) > expiresAt) { query.str(std::string()); query << "DELETE FROM `ip_bans` WHERE `ip` = " << clientIP; diff --git a/src/creatures/players/management/ban.hpp b/src/creatures/players/management/ban.hpp index 6fdb94296df..3e9b3f07f58 100644 --- a/src/creatures/players/management/ban.hpp +++ b/src/creatures/players/management/ban.hpp @@ -10,18 +10,18 @@ #pragma once struct BanInfo { - std::string bannedBy; - std::string reason; - time_t expiresAt; + std::string bannedBy {}; + std::string reason {}; + time_t expiresAt {}; }; struct ConnectBlock { constexpr ConnectBlock(uint64_t lastAttempt, uint64_t blockTime, uint32_t count) : lastAttempt(lastAttempt), blockTime(blockTime), count(count) { } - uint64_t lastAttempt; - uint64_t blockTime; - uint32_t count; + uint64_t lastAttempt {}; + uint64_t blockTime {}; + uint32_t count {}; }; using IpConnectMap = std::map<uint32_t, ConnectBlock>; diff --git a/src/creatures/players/management/waitlist.cpp b/src/creatures/players/management/waitlist.cpp index da658453161..eceb8b70810 100644 --- a/src/creatures/players/management/waitlist.cpp +++ b/src/creatures/players/management/waitlist.cpp @@ -8,7 +8,12 @@ */ #include "creatures/players/management/waitlist.hpp" + +#include "config/configmanager.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" +#include "lib/di/container.hpp" +#include "utils/tools.hpp" #include "enums/account_type.hpp" @@ -25,13 +30,13 @@ WaitingList &WaitingList::getInstance() { return inject<WaitingList>(); } -void WaitingList::cleanupList(WaitList &list) { - int64_t time = OTSYS_TIME(); +void WaitingList::cleanupList(WaitList &list) const { + const int64_t time = OTSYS_TIME(); auto it = list.begin(); while (it != list.end()) { - auto timeout = static_cast<int64_t>(it->timeout); - g_logger().warn("time: {}", timeout - time); + const auto timeout = static_cast<int64_t>(it->timeout); + g_logger().debug("[{}] time: {}", __FUNCTION__, timeout - time); if ((timeout - time) <= 0) { info->playerReferences.erase(it->playerGUID); it = list.erase(it); @@ -41,25 +46,27 @@ void WaitingList::cleanupList(WaitList &list) { } } -std::size_t WaitingList::getTimeout(std::size_t slot) { +std::size_t WaitingList::getTimeout(std::size_t slot) const { return WaitingList::getTime(slot) + TIMEOUT_EXTRA; } std::size_t WaitingList::getTime(std::size_t slot) { if (slot < SLOT_LIMIT_ONE) { return 5; - } else if (slot < SLOT_LIMIT_TWO) { + } + if (slot < SLOT_LIMIT_TWO) { return 10; - } else if (slot < SLOT_LIMIT_THREE) { + } + if (slot < SLOT_LIMIT_THREE) { return 20; - } else if (slot < SLOT_LIMIT_FOUR) { + } + if (slot < SLOT_LIMIT_FOUR) { return 60; - } else { - return 120; } + return 120; } -bool WaitingList::clientLogin(std::shared_ptr<Player> player) { +bool WaitingList::clientLogin(const std::shared_ptr<Player> &player) const { if (player->hasFlag(PlayerFlags_t::CanAlwaysLogin) || player->getAccountType() >= ACCOUNT_TYPE_GAMEMASTER) { return true; } @@ -75,7 +82,7 @@ bool WaitingList::clientLogin(std::shared_ptr<Player> player) { addPlayerToList(player); auto it = info->playerReferences.find(player->getGUID()); - std::size_t slot = it->second.second; + const std::size_t slot = it->second.second; if ((g_game().getPlayersOnline() + slot) <= maxPlayers) { // should be able to login now info->waitList.erase(it->second.first); @@ -85,7 +92,7 @@ bool WaitingList::clientLogin(std::shared_ptr<Player> player) { return false; } -void WaitingList::addPlayerToList(std::shared_ptr<Player> player) { +void WaitingList::addPlayerToList(const std::shared_ptr<Player> &player) const { auto it = info->playerReferences.find(player->getGUID()); if (it != info->playerReferences.end()) { std::size_t slot; @@ -111,7 +118,7 @@ void WaitingList::addPlayerToList(std::shared_ptr<Player> player) { } } -std::size_t WaitingList::getClientSlot(std::shared_ptr<Player> player) { +std::size_t WaitingList::getClientSlot(const std::shared_ptr<Player> &player) const { auto it = info->playerReferences.find(player->getGUID()); if (it == info->playerReferences.end()) { return 0; diff --git a/src/creatures/players/management/waitlist.hpp b/src/creatures/players/management/waitlist.hpp index 24752f2647d..28a21b4a4b1 100644 --- a/src/creatures/players/management/waitlist.hpp +++ b/src/creatures/players/management/waitlist.hpp @@ -34,13 +34,13 @@ class WaitingList { public: WaitingList(); static WaitingList &getInstance(); - bool clientLogin(std::shared_ptr<Player> player); - std::size_t getClientSlot(std::shared_ptr<Player> player); + bool clientLogin(const std::shared_ptr<Player> &player) const; + std::size_t getClientSlot(const std::shared_ptr<Player> &player) const; static std::size_t getTime(std::size_t slot); private: - void cleanupList(WaitList &list); - std::size_t getTimeout(std::size_t slot); - void addPlayerToList(std::shared_ptr<Player> player); + void cleanupList(WaitList &list) const; + std::size_t getTimeout(std::size_t slot) const; + void addPlayerToList(const std::shared_ptr<Player> &player) const; std::unique_ptr<WaitListInfo> info; }; diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 5a6c4cbf6cc..4335db2bd53 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -7,45 +7,66 @@ * Website: https://docs.opentibiabr.com/ */ +#include "creatures/players/player.hpp" + +#include "account/account.hpp" +#include "config/configmanager.hpp" +#include "core.hpp" +#include "creatures/appearance/mounts/mounts.hpp" #include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" #include "creatures/interactions/chat.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/monsters/monsters.hpp" -#include "creatures/players/player.hpp" +#include "creatures/npcs/npc.hpp" #include "creatures/players/wheel/player_wheel.hpp" #include "creatures/players/wheel/wheel_gems.hpp" #include "creatures/players/achievement/player_achievement.hpp" #include "creatures/players/cyclopedia/player_badge.hpp" #include "creatures/players/cyclopedia/player_cyclopedia.hpp" #include "creatures/players/cyclopedia/player_title.hpp" +#include "creatures/players/grouping/party.hpp" +#include "creatures/players/imbuements/imbuements.hpp" #include "creatures/players/storages/storages.hpp" +#include "creatures/players/vip/player_vip.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "server/network/protocol/protocolgame.hpp" +#include "enums/account_errors.hpp" +#include "enums/account_group_type.hpp" +#include "enums/account_type.hpp" +#include "enums/object_category.hpp" +#include "enums/player_blessings.hpp" +#include "enums/player_icons.hpp" #include "game/game.hpp" #include "game/modal_window/modal_window.hpp" #include "game/scheduling/dispatcher.hpp" -#include "game/scheduling/task.hpp" #include "game/scheduling/save_manager.hpp" +#include "game/scheduling/task.hpp" #include "grouping/familiars.hpp" -#include "lua/creature/creatureevent.hpp" -#include "lua/creature/events.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" -#include "lua/creature/movement.hpp" +#include "grouping/guild.hpp" +#include "io/iobestiary.hpp" #include "io/iologindata.hpp" +#include "io/ioprey.hpp" #include "items/bed.hpp" +#include "items/containers/depot/depotchest.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "items/containers/rewards/reward.hpp" +#include "items/containers/rewards/rewardchest.hpp" +#include "items/items_classification.hpp" #include "items/weapons/weapons.hpp" -#include "core.hpp" -#include "map/spectators.hpp" #include "lib/metrics/metrics.hpp" -#include "enums/object_category.hpp" -#include "enums/account_errors.hpp" -#include "enums/account_type.hpp" -#include "enums/account_group_type.hpp" -#include "enums/player_blessings.hpp" +#include "lua/callbacks/event_callback.hpp" +#include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/actions.hpp" +#include "lua/creature/creatureevent.hpp" +#include "lua/creature/events.hpp" +#include "lua/creature/movement.hpp" +#include "map/spectators.hpp" +#include "creatures/players/vocations/vocation.hpp" MuteCountMap Player::muteCountMap; -Player::Player(ProtocolGame_ptr p) : - Creature(), +Player::Player(std::shared_ptr<ProtocolGame> p) : lastPing(OTSYS_TIME()), lastPong(lastPing), inbox(std::make_shared<Inbox>(ITEM_INBOX)), @@ -59,19 +80,20 @@ Player::Player(ProtocolGame_ptr p) : } Player::~Player() { - for (const std::shared_ptr<Item> &item : inventory) { + for (const auto &item : inventory) { if (item) { item->resetParent(); item->stopDecaying(); } } - for (const auto &it : depotLockerMap) { - it.second->removeInbox(inbox); - it.second->stopDecaying(); - } + for (const auto &[depotId, depotLocker] : depotLockerMap) { + if (depotId == 0) { + continue; + } - inbox->stopDecaying(); + depotLocker->removeInbox(inbox); + } setWriteItem(nullptr); setEditHouse(nullptr); @@ -90,6 +112,10 @@ bool Player::setVocation(uint16_t vocId) { return true; } +uint16_t Player::getVocationId() const { + return vocation->getId(); +} + bool Player::isPushable() { if (hasFlag(PlayerFlags_t::CannotBePushed)) { return false; @@ -97,8 +123,8 @@ bool Player::isPushable() { return Creature::isPushable(); } -std::shared_ptr<Task> Player::createPlayerTask(uint32_t delay, std::function<void(void)> f, std::string context) { - return std::make_shared<Task>(std::move(f), std::move(context), delay); +std::shared_ptr<Task> Player::createPlayerTask(uint32_t delay, std::function<void(void)> f, const std::string &context) { + return std::make_shared<Task>(std::move(f), context, delay); } uint32_t Player::playerFirstID = 0x10000000; @@ -124,7 +150,7 @@ std::string Player::getDescription(int32_t lookDistance) { std::ostringstream s; std::string subjectPronoun = getSubjectPronoun(); capitalizeWords(subjectPronoun); - auto playerTitle = title()->getCurrentTitle() == 0 ? "" : (", " + title()->getCurrentTitleName()); + const auto playerTitle = title()->getCurrentTitle() == 0 ? "" : (", " + title()->getCurrentTitleName()); if (lookDistance == -1) { s << "yourself" << playerTitle << "."; @@ -180,14 +206,14 @@ std::string Player::getDescription(int32_t lookDistance) { s << " " << subjectPronoun << " " << getSubjectVerb() << " in a party with "; } - size_t memberCount = m_party->getMemberCount() + 1; + const size_t memberCount = m_party->getMemberCount() + 1; if (memberCount == 1) { s << "1 member and "; } else { s << memberCount << " members and "; } - size_t invitationCount = m_party->getInvitationCount(); + const size_t invitationCount = m_party->getInvitationCount(); if (invitationCount == 1) { s << "1 pending invitation."; } else { @@ -196,7 +222,7 @@ std::string Player::getDescription(int32_t lookDistance) { } if (guild && guildRank) { - size_t memberCount = guild->getMemberCount(); + const size_t memberCount = guild->getMemberCount(); if (memberCount >= 1000) { s << ""; return s.str(); @@ -229,6 +255,18 @@ std::shared_ptr<Item> Player::getInventoryItem(Slots_t slot) const { return inventory[slot]; } +bool Player::isItemAbilityEnabled(Slots_t slot) const { + return inventoryAbilities[slot]; +} + +void Player::setItemAbility(Slots_t slot, bool enabled) { + inventoryAbilities[slot] = enabled; +} + +void Player::setVarSkill(skills_t skill, int32_t modifier) { + varSkills[skill] += modifier; +} + bool Player::isSuppress(ConditionType_t conditionType, bool attackerPlayer) const { auto minDelay = g_configManager().getNumber(MIN_DELAY_BETWEEN_CONDITIONS); if (IsConditionSuppressible(conditionType) && checkLastConditionTimeWithin(conditionType, minDelay)) { @@ -249,12 +287,12 @@ void Player::removeConditionSuppressions() { } std::shared_ptr<Item> Player::getWeapon(Slots_t slot, bool ignoreAmmo) const { - std::shared_ptr<Item> item = inventory[slot]; + const auto &item = inventory[slot]; if (!item) { return nullptr; } - WeaponType_t weaponType = item->getWeaponType(); + const WeaponType_t &weaponType = item->getWeaponType(); if (weaponType == WEAPON_NONE || weaponType == WEAPON_SHIELD || weaponType == WEAPON_AMMO) { return nullptr; } @@ -262,7 +300,7 @@ std::shared_ptr<Item> Player::getWeapon(Slots_t slot, bool ignoreAmmo) const { if (!ignoreAmmo && (weaponType == WEAPON_DISTANCE || weaponType == WEAPON_MISSILE)) { const ItemType &it = Item::items[item->getID()]; if (it.ammoType != AMMO_NONE) { - item = getQuiverAmmoOfType(it); + return getQuiverAmmoOfType(it); } } @@ -270,12 +308,12 @@ std::shared_ptr<Item> Player::getWeapon(Slots_t slot, bool ignoreAmmo) const { } bool Player::hasQuiverEquipped() const { - std::shared_ptr<Item> quiver = inventory[CONST_SLOT_RIGHT]; + const auto &quiver = inventory[CONST_SLOT_RIGHT]; return quiver && quiver->isQuiver() && quiver->getContainer(); } bool Player::hasWeaponDistanceEquipped() const { - std::shared_ptr<Item> item = inventory[CONST_SLOT_LEFT]; + const auto &item = inventory[CONST_SLOT_LEFT]; return item && item->getWeaponType() == WEAPON_DISTANCE; } @@ -284,9 +322,9 @@ std::shared_ptr<Item> Player::getQuiverAmmoOfType(const ItemType &it) const { return nullptr; } - std::shared_ptr<Item> quiver = inventory[CONST_SLOT_RIGHT]; - for (std::shared_ptr<Container> container = quiver->getContainer(); - auto ammoItem : container->getItemList()) { + const auto &quiver = inventory[CONST_SLOT_RIGHT]; + for (const auto &container = quiver->getContainer(); + const auto &ammoItem : container->getItemList()) { if (ammoItem->getAmmoType() == it.ammoType) { if (level >= Item::items[ammoItem->getID()].minReqLevel) { return ammoItem; @@ -297,34 +335,34 @@ std::shared_ptr<Item> Player::getQuiverAmmoOfType(const ItemType &it) const { } std::shared_ptr<Item> Player::getWeapon(bool ignoreAmmo /* = false*/) const { - std::shared_ptr<Item> item = getWeapon(CONST_SLOT_LEFT, ignoreAmmo); - if (item) { - return item; + const auto &itemLeft = getWeapon(CONST_SLOT_LEFT, ignoreAmmo); + if (itemLeft) { + return itemLeft; } - item = getWeapon(CONST_SLOT_RIGHT, ignoreAmmo); - if (item) { - return item; + const auto &itemRight = getWeapon(CONST_SLOT_RIGHT, ignoreAmmo); + if (itemRight) { + return itemRight; } return nullptr; } WeaponType_t Player::getWeaponType() const { - std::shared_ptr<Item> item = getWeapon(); + const auto &item = getWeapon(); if (!item) { return WEAPON_NONE; } return item->getWeaponType(); } -int32_t Player::getWeaponSkill(std::shared_ptr<Item> item) const { +int32_t Player::getWeaponSkill(const std::shared_ptr<Item> &item) const { if (!item) { return getSkillLevel(SKILL_FIST); } int32_t attackSkill; - WeaponType_t weaponType = item->getWeaponType(); + const WeaponType_t &weaponType = item->getWeaponType(); switch (weaponType) { case WEAPON_SWORD: { attackSkill = getSkillLevel(SKILL_SWORD); @@ -358,14 +396,14 @@ int32_t Player::getWeaponSkill(std::shared_ptr<Item> item) const { int32_t Player::getArmor() const { int32_t armor = 0; - static const Slots_t armorSlots[] = { CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_ARMOR, CONST_SLOT_LEGS, CONST_SLOT_FEET, CONST_SLOT_RING, CONST_SLOT_AMMO }; - for (Slots_t slot : armorSlots) { - std::shared_ptr<Item> inventoryItem = inventory[slot]; + static constexpr Slots_t armorSlots[] = { CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_ARMOR, CONST_SLOT_LEGS, CONST_SLOT_FEET, CONST_SLOT_RING, CONST_SLOT_AMMO }; + for (const Slots_t &slot : armorSlots) { + const auto &inventoryItem = inventory[slot]; if (inventoryItem) { armor += inventoryItem->getArmor(); } } - return static_cast<int32_t>(armor * vocation->armorMultiplier); + return armor * static_cast<int32_t>(vocation->armorMultiplier); } void Player::getShieldAndWeapon(std::shared_ptr<Item> &shield, std::shared_ptr<Item> &weapon) const { @@ -373,7 +411,7 @@ void Player::getShieldAndWeapon(std::shared_ptr<Item> &shield, std::shared_ptr<I weapon = nullptr; for (uint32_t slot = CONST_SLOT_RIGHT; slot <= CONST_SLOT_LEFT; slot++) { - std::shared_ptr<Item> item = inventory[slot]; + const auto &item = inventory[slot]; if (!item) { continue; } @@ -466,6 +504,18 @@ float Player::getDefenseFactor() const { } } +void Player::setLastWalkthroughAttempt(int64_t walkthroughAttempt) { + lastWalkthroughAttempt = walkthroughAttempt; +} + +void Player::setLastWalkthroughPosition(Position walkthroughPosition) { + lastWalkthroughPosition = walkthroughPosition; +} + +std::shared_ptr<Inbox> Player::getInbox() const { + return inbox; +} + std::unordered_set<PlayerIcon> Player::getClientIcons() { std::unordered_set<PlayerIcon> icons; @@ -483,7 +533,7 @@ std::unordered_set<PlayerIcon> Player::getClientIcons() { icons.insert(PlayerIcon::RedSwords); } - auto tile = getTile(); + const auto &tile = getTile(); if (tile && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { if (icons.size() < 9) { icons.insert(PlayerIcon::Pigeon); @@ -498,7 +548,11 @@ std::unordered_set<PlayerIcon> Player::getClientIcons() { return icons; } -void Player::addMonsterToCyclopediaTrackerList(const std::shared_ptr<MonsterType> mtype, bool isBoss, bool reloadClient /* = false */) { +const std::unordered_set<std::shared_ptr<MonsterType>> &Player::getCyclopediaMonsterTrackerSet(bool isBoss) const { + return isBoss ? m_bosstiaryMonsterTracker : m_bestiaryMonsterTracker; +} + +void Player::addMonsterToCyclopediaTrackerList(const std::shared_ptr<MonsterType> &mtype, bool isBoss, bool reloadClient /* = false */) { if (!client) { return; } @@ -518,7 +572,7 @@ void Player::addMonsterToCyclopediaTrackerList(const std::shared_ptr<MonsterType } } -void Player::removeMonsterFromCyclopediaTrackerList(std::shared_ptr<MonsterType> mtype, bool isBoss, bool reloadClient /* = false */) { +void Player::removeMonsterFromCyclopediaTrackerList(const std::shared_ptr<MonsterType> &mtype, bool isBoss, bool reloadClient /* = false */) { if (!client) { return; } @@ -539,10 +593,79 @@ void Player::removeMonsterFromCyclopediaTrackerList(std::shared_ptr<MonsterType> } } +void Player::sendBestiaryEntryChanged(uint16_t raceid) const { + if (client) { + client->sendBestiaryEntryChanged(raceid); + } +} + +void Player::refreshCyclopediaMonsterTracker(const std::unordered_set<std::shared_ptr<MonsterType>> &trackerList, bool isBoss) const { + if (client) { + client->refreshCyclopediaMonsterTracker(trackerList, isBoss); + } +} + bool Player::isBossOnBosstiaryTracker(const std::shared_ptr<MonsterType> &monsterType) const { return monsterType ? m_bosstiaryMonsterTracker.contains(monsterType) : false; } +std::shared_ptr<Vocation> Player::getVocation() const { + return vocation; +} + +OperatingSystem_t Player::getOperatingSystem() const { + return operatingSystem; +} + +void Player::setOperatingSystem(OperatingSystem_t clientos) { + operatingSystem = clientos; +} + +bool Player::isOldProtocol() const { + return client && client->oldProtocol; +} + +uint32_t Player::getProtocolVersion() const { + if (!client) { + return 0; + } + + return client->getVersion(); +} + +bool Player::hasSecureMode() const { + return secureMode; +} + +void Player::setParty(std::shared_ptr<Party> newParty) { + m_party = std::move(newParty); +} + +std::shared_ptr<Party> Player::getParty() const { + return m_party; +} + +int32_t Player::getCleavePercent(bool useCharges) const { + int32_t result = cleavePercent; + for (const auto &item : getEquippedItems()) { + const ItemType &it = Item::items[item->getID()]; + if (!it.abilities) { + continue; + } + + const int32_t &cleave_percent = it.abilities->cleavePercent; + if (cleave_percent != 0) { + result += cleave_percent; + const uint16_t charges = item->getCharges(); + if (useCharges && charges != 0) { + g_game().transformItem(item, item->getID(), charges - 1); + } + } + } + + return result; +} + void Player::updateInventoryWeight() { if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { return; @@ -550,7 +673,7 @@ void Player::updateInventoryWeight() { inventoryWeight = 0; for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (item) { inventoryWeight += item->getWeight(); } @@ -559,17 +682,16 @@ void Player::updateInventoryWeight() { void Player::updateInventoryImbuement() { // Get the tile the player is currently on - std::shared_ptr<Tile> playerTile = getTile(); + const auto &playerTile = getTile(); // Check if the player is in a protection zone - bool isInProtectionZone = playerTile && playerTile->hasFlag(TILESTATE_PROTECTIONZONE); + const bool &isInProtectionZone = playerTile && playerTile->hasFlag(TILESTATE_PROTECTIONZONE); // Check if the player is in fight mode bool isInFightMode = hasCondition(CONDITION_INFIGHT); bool nonAggressiveFightOnly = g_configManager().getBoolean(TOGGLE_IMBUEMENT_NON_AGGRESSIVE_FIGHT_ONLY); // Iterate through all items in the player's inventory - for (auto [key, item] : getAllSlotItems()) { + for (const auto &[slodNumber, item] : getAllSlotItems()) { // Iterate through all imbuement slots on the item - for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { ImbuementInfo imbuementInfo; // Get the imbuement information for the current slot @@ -579,12 +701,12 @@ void Player::updateInventoryImbuement() { } // Imbuement from imbuementInfo, this variable reduces code complexity - auto imbuement = imbuementInfo.imbuement; + const auto imbuement = imbuementInfo.imbuement; // Get the category of the imbuement const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory()); // Parent of the imbued item - auto parent = item->getParent(); - bool isInBackpack = parent && parent->getContainer(); + const auto &parent = item->getParent(); + const bool &isInBackpack = parent && parent->getContainer(); // If the imbuement is aggressive and the player is not in fight mode or is in a protection zone, or the item is in a container, ignore it. if (categoryImbuement && (categoryImbuement->agressive || nonAggressiveFightOnly) && (isInProtectionZone || !isInFightMode || isInBackpack)) { continue; @@ -603,14 +725,13 @@ void Player::updateInventoryImbuement() { g_logger().trace("Decaying imbuement {} from item {} of player {}", imbuement->getName(), item->getName(), getName()); // Calculate the new duration of the imbuement, making sure it doesn't go below 0 - uint32_t duration = std::max<uint32_t>(0, imbuementInfo.duration - EVENT_IMBUEMENT_INTERVAL / 1000); + const uint32_t duration = std::max<uint32_t>(0, imbuementInfo.duration - EVENT_IMBUEMENT_INTERVAL / 1000); // Update the imbuement's duration in the item item->decayImbuementTime(slotid, imbuement->getID(), duration); if (duration == 0) { removeItemImbuementStats(imbuement); updateImbuementTrackerStats(); - continue; } } } @@ -619,7 +740,7 @@ void Player::updateInventoryImbuement() { phmap::flat_hash_map<uint8_t, std::shared_ptr<Item>> Player::getAllSlotItems() const { phmap::flat_hash_map<uint8_t, std::shared_ptr<Item>> itemMap; for (uint8_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (!item) { continue; } @@ -630,16 +751,6 @@ phmap::flat_hash_map<uint8_t, std::shared_ptr<Item>> Player::getAllSlotItems() c return itemMap; } -void Player::setTraining(bool value) { - for (const auto &[key, player] : g_game().getPlayers()) { - if (!this->isInGhostMode() || player->isAccessPlayer()) { - player->vip()->notifyStatusChange(static_self_cast<Player>(), value ? VipStatus_t::Training : VipStatus_t::Online, false); - } - } - vip()->setStatus(VipStatus_t::Training); - setExerciseTraining(value); -} - uint16_t Player::getLoyaltySkill(skills_t skill) const { uint16_t level = getBaseSkill(skill); absl::uint128 currReqTries = vocation->getReqSkillTries(skill, level); @@ -650,7 +761,7 @@ uint16_t Player::getLoyaltySkill(skills_t skill) const { } absl::uint128 tries = skills[skill].tries; - absl::uint128 totalTries = vocation->getTotalSkillTries(skill, skills[skill].level) + tries; + const absl::uint128 totalTries = vocation->getTotalSkillTries(skill, skills[skill].level) + tries; absl::uint128 loyaltyTries = (totalTries * getLoyaltyBonus()) / 100; while ((tries + loyaltyTries) >= nextReqTries) { loyaltyTries -= nextReqTries - tries; @@ -667,6 +778,69 @@ uint16_t Player::getLoyaltySkill(skills_t skill) const { return level; } +uint16_t Player::getBaseSkill(uint8_t skill) const { + return skills[skill].level; +} + +double_t Player::getSkillPercent(skills_t skill) const { + return skills[skill].percent; +} + +bool Player::getAddAttackSkill() const { + return addAttackSkillPoint; +} + +BlockType_t Player::getLastAttackBlockType() const { + return lastAttackBlockType; +} + +uint64_t Player::getLastConditionTime(ConditionType_t type) const { + if (!lastConditionTime.contains(static_cast<uint8_t>(type))) { + return 0; + } + return lastConditionTime.at(static_cast<uint8_t>(type)); +} + +void Player::updateLastConditionTime(ConditionType_t type) { + lastConditionTime[static_cast<uint8_t>(type)] = OTSYS_TIME(); +} + +bool Player::checkLastConditionTimeWithin(ConditionType_t type, uint32_t interval) const { + if (!lastConditionTime.contains(static_cast<uint8_t>(type))) { + return false; + } + const auto last = lastConditionTime.at(static_cast<uint8_t>(type)); + return last > 0 && ((OTSYS_TIME() - last) < interval); +} + +uint64_t Player::getLastAttack() const { + return lastAttack; +} + +bool Player::checkLastAttackWithin(uint32_t interval) const { + return lastAttack > 0 && ((OTSYS_TIME() - lastAttack) < interval); +} + +void Player::updateLastAttack() { + if (lastAttack == 0) { + lastAttack = OTSYS_TIME() - getAttackSpeed() - 1; + return; + } + lastAttack = OTSYS_TIME(); +} + +uint64_t Player::getLastAggressiveAction() const { + return lastAggressiveAction; +} + +bool Player::checkLastAggressiveActionWithin(uint32_t interval) const { + return lastAggressiveAction > 0 && ((OTSYS_TIME() - lastAggressiveAction) < interval); +} + +void Player::updateLastAggressiveAction() { + lastAggressiveAction = OTSYS_TIME(); +} + void Player::addSkillAdvance(skills_t skill, uint64_t count) { uint64_t currReqTries = vocation->getReqSkillTries(skill, skills[skill].level); uint64_t nextReqTries = vocation->getReqSkillTries(skill, skills[skill].level + 1); @@ -769,7 +943,7 @@ int32_t Player::getDefaultStats(stats_t stat) const { } } -void Player::addContainer(uint8_t cid, std::shared_ptr<Container> container) { +void Player::addContainer(uint8_t cid, const std::shared_ptr<Container> &container) { if (cid > 0xF) { return; } @@ -778,13 +952,9 @@ void Player::addContainer(uint8_t cid, std::shared_ptr<Container> container) { return; } - auto it = openContainers.find(cid); + const auto it = openContainers.find(cid); if (it != openContainers.end()) { OpenContainer &openContainer = it->second; - auto oldContainer = openContainer.container; - if (oldContainer->getID() == ITEM_BROWSEFIELD) { - } - openContainer.container = container; openContainer.index = 0; } else { @@ -796,20 +966,18 @@ void Player::addContainer(uint8_t cid, std::shared_ptr<Container> container) { } void Player::closeContainer(uint8_t cid) { - auto it = openContainers.find(cid); + const auto it = openContainers.find(cid); if (it == openContainers.end()) { return; } - OpenContainer openContainer = it->second; - std::shared_ptr<Container> container = openContainer.container; + const OpenContainer &openContainer = it->second; + const auto &container = openContainer.container; if (container && container->isAnyKindOfRewardChest() && !hasOtherRewardContainerOpen(container)) { removeEmptyRewards(); } openContainers.erase(it); - if (container && container->getID() == ITEM_BROWSEFIELD) { - } } void Player::removeEmptyRewards() { @@ -823,14 +991,14 @@ void Player::removeEmptyRewards() { }); } -bool Player::hasOtherRewardContainerOpen(const std::shared_ptr<Container> container) const { +bool Player::hasOtherRewardContainerOpen(const std::shared_ptr<Container> &container) const { return std::ranges::any_of(openContainers.begin(), openContainers.end(), [container](const auto &containerPair) { return containerPair.second.container != container && containerPair.second.container->isAnyKindOfRewardContainer(); }); } void Player::setContainerIndex(uint8_t cid, uint16_t index) { - auto it = openContainers.find(cid); + const auto it = openContainers.find(cid); if (it == openContainers.end()) { return; } @@ -838,24 +1006,24 @@ void Player::setContainerIndex(uint8_t cid, uint16_t index) { } std::shared_ptr<Container> Player::getContainerByID(uint8_t cid) { - auto it = openContainers.find(cid); + const auto it = openContainers.find(cid); if (it == openContainers.end()) { return nullptr; } return it->second.container; } -int8_t Player::getContainerID(std::shared_ptr<Container> container) const { - for (const auto &it : openContainers) { - if (it.second.container == container) { - return it.first; +int8_t Player::getContainerID(const std::shared_ptr<Container> &container) const { + for (const auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container == container) { + return containerId; } } return -1; } uint16_t Player::getContainerIndex(uint8_t cid) const { - auto it = openContainers.find(cid); + const auto it = openContainers.find(cid); if (it == openContainers.end()) { return 0; } @@ -869,9 +1037,8 @@ bool Player::canOpenCorpse(uint32_t ownerId) const { uint16_t Player::getLookCorpse() const { if (sex == PLAYERSEX_FEMALE) { return ITEM_FEMALE_CORPSE; - } else { - return ITEM_MALE_CORPSE; } + return ITEM_MALE_CORPSE; } void Player::addStorageValue(const uint32_t key, const int32_t value, const bool isLogin /* = false*/) { @@ -882,7 +1049,8 @@ void Player::addStorageValue(const uint32_t key, const int32_t value, const bool value & 0xFF ); return; - } else if (IS_IN_KEYRANGE(key, MOUNTS_RANGE)) { + } + if (IS_IN_KEYRANGE(key, MOUNTS_RANGE)) { // do nothing } else if (IS_IN_KEYRANGE(key, FAMILIARS_RANGE)) { familiars.emplace_back( @@ -911,7 +1079,7 @@ void Player::addStorageValue(const uint32_t key, const int32_t value, const bool int32_t Player::getStorageValue(const uint32_t key) const { int32_t value = -1; - auto it = storageMap.find(key); + const auto it = storageMap.find(key); if (it == storageMap.end()) { return value; } @@ -921,11 +1089,11 @@ int32_t Player::getStorageValue(const uint32_t key) const { } int32_t Player::getStorageValueByName(const std::string &storageName) const { - auto it = g_storages().getStorageMap().find(storageName); + const auto it = g_storages().getStorageMap().find(storageName); if (it == g_storages().getStorageMap().end()) { return -1; } - uint32_t key = it->second; + const uint32_t key = it->second; return getStorageValue(key); } @@ -936,10 +1104,14 @@ void Player::addStorageValueByName(const std::string &storageName, const int32_t g_logger().error("[{}] Storage name '{}' not found in storage map, register your storage in 'storages.xml' first for use", __func__, storageName); return; } - uint32_t key = it->second; + const uint32_t key = it->second; addStorageValue(key, value, isLogin); } +std::shared_ptr<KV> Player::kv() const { + return g_kv().scoped("player")->scoped(fmt::format("{}", getGUID())); +} + bool Player::canSee(const Position &pos) { if (!client) { return false; @@ -947,7 +1119,7 @@ bool Player::canSee(const Position &pos) { return client->canSee(pos); } -bool Player::canSeeCreature(std::shared_ptr<Creature> creature) const { +bool Player::canSeeCreature(const std::shared_ptr<Creature> &creature) const { if (creature.get() == this) { return true; } @@ -962,14 +1134,14 @@ bool Player::canSeeCreature(std::shared_ptr<Creature> creature) const { return true; } -bool Player::canWalkthrough(std::shared_ptr<Creature> creature) { +bool Player::canWalkthrough(const std::shared_ptr<Creature> &creature) { if (group->access || creature->isInGhostMode()) { return true; } - std::shared_ptr<Player> player = creature->getPlayer(); - std::shared_ptr<Monster> monster = creature->getMonster(); - std::shared_ptr<Npc> npc = creature->getNpc(); + const auto &player = creature->getPlayer(); + const auto &monster = creature->getMonster(); + const auto &npc = creature->getNpc(); if (monster) { if (!monster->isFamiliar()) { return false; @@ -978,17 +1150,17 @@ bool Player::canWalkthrough(std::shared_ptr<Creature> creature) { } if (player) { - std::shared_ptr<Tile> playerTile = player->getTile(); + const auto &playerTile = player->getTile(); if (!playerTile || (!playerTile->hasFlag(TILESTATE_NOPVPZONE) && !playerTile->hasFlag(TILESTATE_PROTECTIONZONE) && player->getLevel() > static_cast<uint32_t>(g_configManager().getNumber(PROTECTION_LEVEL)) && g_game().getWorldType() != WORLD_TYPE_NO_PVP)) { return false; } - std::shared_ptr<Item> playerTileGround = playerTile->getGround(); + const auto &playerTileGround = playerTile->getGround(); if (!playerTileGround || !playerTileGround->hasWalkStack()) { return false; } - std::shared_ptr<Player> thisPlayer = getPlayer(); + const auto &thisPlayer = getPlayer(); if ((OTSYS_TIME() - lastWalkthroughAttempt) > 2000) { thisPlayer->setLastWalkthroughAttempt(OTSYS_TIME()); return false; @@ -1002,20 +1174,20 @@ bool Player::canWalkthrough(std::shared_ptr<Creature> creature) { thisPlayer->setLastWalkthroughPosition(creature->getPosition()); return true; } else if (npc) { - std::shared_ptr<Tile> tile = npc->getTile(); - std::shared_ptr<HouseTile> houseTile = std::dynamic_pointer_cast<HouseTile>(tile); + const auto &tile = npc->getTile(); + const auto &houseTile = std::dynamic_pointer_cast<HouseTile>(tile); return (houseTile != nullptr); } return false; } -bool Player::canWalkthroughEx(std::shared_ptr<Creature> creature) { +bool Player::canWalkthroughEx(const std::shared_ptr<Creature> &creature) const { if (group->access) { return true; } - std::shared_ptr<Monster> monster = creature->getMonster(); + const auto &monster = creature->getMonster(); if (monster) { if (!monster->isFamiliar()) { return false; @@ -1023,29 +1195,90 @@ bool Player::canWalkthroughEx(std::shared_ptr<Creature> creature) { return true; } - std::shared_ptr<Player> player = creature->getPlayer(); - std::shared_ptr<Npc> npc = creature->getNpc(); + const auto &player = creature->getPlayer(); + const auto &npc = creature->getNpc(); if (player) { - std::shared_ptr<Tile> playerTile = player->getTile(); + const auto &playerTile = player->getTile(); return playerTile && (playerTile->hasFlag(TILESTATE_NOPVPZONE) || playerTile->hasFlag(TILESTATE_PROTECTIONZONE) || player->getLevel() <= static_cast<uint32_t>(g_configManager().getNumber(PROTECTION_LEVEL)) || g_game().getWorldType() == WORLD_TYPE_NO_PVP); } else if (npc) { - std::shared_ptr<Tile> tile = npc->getTile(); - std::shared_ptr<HouseTile> houseTile = std::dynamic_pointer_cast<HouseTile>(tile); + const auto &tile = npc->getTile(); + const auto &houseTile = std::dynamic_pointer_cast<HouseTile>(tile); return (houseTile != nullptr); } else { return false; } } +RaceType_t Player::getRace() const { + return RACE_BLOOD; +} + +uint64_t Player::getMoney() const { + uint64_t moneyCount = 0; + + auto countMoneyInContainer = [&moneyCount](const auto &self, const std::shared_ptr<Container> &container) -> void { + for (const auto &item : container->getItemList()) { + if (const auto &tmpContainer = item->getContainer()) { + self(self, tmpContainer); + } else { + moneyCount += item->getWorth(); + } + } + }; + + for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { + const auto &item = inventory[i]; + if (!item) { + continue; + } + + if (const auto &container = item->getContainer()) { + countMoneyInContainer(countMoneyInContainer, container); + } else { + moneyCount += item->getWorth(); + } + } + + return moneyCount; +} + +std::pair<uint64_t, uint64_t> Player::getForgeSliversAndCores() const { + uint64_t sliverCount = 0; + uint64_t coreCount = 0; + + // Check items from inventory + for (const auto &item : getAllInventoryItems()) { + if (!item) { + continue; + } + + sliverCount += item->getForgeSlivers(); + coreCount += item->getForgeCores(); + } + + // Check items from stash + for (const auto &stashToSend = getStashItems(); + const auto &[itemId, itemCount] : stashToSend) { + if (itemId == ITEM_FORGE_SLIVER) { + sliverCount += itemCount; + } + if (itemId == ITEM_FORGE_CORE) { + coreCount += itemCount; + } + } + + return std::make_pair(sliverCount, coreCount); +} + void Player::onReceiveMail() { if (isNearDepotBox()) { sendTextMessage(MESSAGE_EVENT_ADVANCE, "New mail has arrived."); } } -std::shared_ptr<Container> Player::refreshManagedContainer(ObjectCategory_t category, std::shared_ptr<Container> container, bool isLootContainer, bool loading /* = false*/) { +std::shared_ptr<Container> Player::refreshManagedContainer(ObjectCategory_t category, const std::shared_ptr<Container> &container, bool isLootContainer, bool loading /* = false*/) { std::shared_ptr<Container> previousContainer = nullptr; - auto toSetAttribute = isLootContainer ? ItemAttribute_t::QUICKLOOTCONTAINER : ItemAttribute_t::OBTAINCONTAINER; + const auto toSetAttribute = isLootContainer ? ItemAttribute_t::QUICKLOOTCONTAINER : ItemAttribute_t::OBTAINCONTAINER; if (auto it = m_managedContainers.find(category); it != m_managedContainers.end() && !loading) { previousContainer = isLootContainer ? it->second.first : it->second.second; if (previousContainer) { @@ -1071,7 +1304,7 @@ std::shared_ptr<Container> Player::refreshManagedContainer(ObjectCategory_t cate if (container) { previousContainer = container; - if (m_managedContainers.find(category) != m_managedContainers.end()) { + if (m_managedContainers.contains(category)) { if (isLootContainer) { m_managedContainers[category].first = container; } else { @@ -1090,8 +1323,8 @@ std::shared_ptr<Container> Player::refreshManagedContainer(ObjectCategory_t cate } if (!loading) { - auto flags = container->getAttribute<uint32_t>(toSetAttribute); - auto sendAttribute = flags | (1 << category); + const auto flags = container->getAttribute<uint32_t>(toSetAttribute); + const auto sendAttribute = flags | (1 << category); container->setAttribute(toSetAttribute, sendAttribute); } } @@ -1104,7 +1337,7 @@ std::shared_ptr<Container> Player::getManagedContainer(ObjectCategory_t category category = OBJECTCATEGORY_DEFAULT; } - auto it = m_managedContainers.find(category); + const auto it = m_managedContainers.find(category); std::shared_ptr<Container> container = nullptr; if (it != m_managedContainers.end()) { container = isLootContainer ? it->second.first : it->second.second; @@ -1118,15 +1351,15 @@ std::shared_ptr<Container> Player::getManagedContainer(ObjectCategory_t category return container; } -void Player::checkLootContainers(std::shared_ptr<Container> container) { +void Player::checkLootContainers(const std::shared_ptr<Container> &container) { if (!container) { return; } bool shouldSend = false; for (auto it = m_managedContainers.begin(); it != m_managedContainers.end();) { - std::shared_ptr<Container> &lootContainer = it->second.first; - std::shared_ptr<Container> &obtainContainer = it->second.second; + auto &lootContainer = it->second.first; + auto &obtainContainer = it->second.second; bool removeLoot = false; bool removeObtain = false; if (lootContainer && container->getHoldingPlayer() != getPlayer() && (container == lootContainer || container->isHoldingItem(lootContainer))) { @@ -1161,15 +1394,15 @@ void Player::checkLootContainers(std::shared_ptr<Container> container) { } } -void Player::setMainBackpackUnassigned(std::shared_ptr<Container> container) { +void Player::setMainBackpackUnassigned(const std::shared_ptr<Container> &container) { if (!container) { return; } // Update containers bool toSendInventoryUpdate = false; - for (bool isLootContainer : { true, false }) { - std::shared_ptr<Container> managedContainer = getManagedContainer(OBJECTCATEGORY_DEFAULT, isLootContainer); + for (const bool isLootContainer : { true, false }) { + const auto &managedContainer = getManagedContainer(OBJECTCATEGORY_DEFAULT, isLootContainer); if (!managedContainer) { refreshManagedContainer(OBJECTCATEGORY_DEFAULT, container, isLootContainer); toSendInventoryUpdate = true; @@ -1182,7 +1415,22 @@ void Player::setMainBackpackUnassigned(std::shared_ptr<Container> container) { } } -void Player::sendLootStats(std::shared_ptr<Item> item, uint8_t count) { +bool Player::updateKillTracker(const std::shared_ptr<Container> &corpse, const std::string &playerName, const Outfit_t &creatureOutfit) const { + if (client) { + client->sendKillTrackerUpdate(corpse, playerName, creatureOutfit); + return true; + } + + return false; +} + +void Player::updatePartyTrackerAnalyzer() const { + if (client && m_party) { + client->updatePartyTrackerAnalyzer(m_party); + } +} + +void Player::sendLootStats(const std::shared_ptr<Item> &item, uint8_t count) { uint64_t value = 0; if (item->getID() == ITEM_GOLD_COIN || item->getID() == ITEM_PLATINUM_COIN || item->getID() == ITEM_CRYSTAL_COIN) { if (item->getID() == ITEM_PLATINUM_COIN) { @@ -1193,7 +1441,7 @@ void Player::sendLootStats(std::shared_ptr<Item> item, uint8_t count) { value = count; } } else if ( - auto npc = g_game().getNpcByName("The Lootmonger") + const auto &npc = g_game().getNpcByName("The Lootmonger") ) { const auto &iType = Item::items.getItemType(item->getID()); value = iType.sellPrice * count; @@ -1209,42 +1457,295 @@ void Player::sendLootStats(std::shared_ptr<Item> item, uint8_t count) { } } -bool Player::isNearDepotBox() { - const Position &pos = getPosition(); - for (int32_t cx = -1; cx <= 1; ++cx) { - for (int32_t cy = -1; cy <= 1; ++cy) { - std::shared_ptr<Tile> posTile = g_game().map.getTile(static_cast<uint16_t>(pos.x + cx), static_cast<uint16_t>(pos.y + cy), pos.z); - if (!posTile) { - continue; - } +void Player::updateSupplyTracker(const std::shared_ptr<Item> &item) { + const auto &iType = Item::items.getItemType(item->getID()); + const auto value = iType.buyPrice; + g_metrics().addCounter("player_supply", value, { { "player", getName() } }); - if (posTile->hasFlag(TILESTATE_DEPOT)) { - return true; - } - } + if (client) { + client->sendUpdateSupplyTracker(item); } - return false; -} -std::shared_ptr<DepotChest> Player::getDepotChest(uint32_t depotId, bool autoCreate) { - auto it = depotChests.find(depotId); - if (it != depotChests.end()) { - return it->second; + if (m_party) { + m_party->addPlayerSupply(getPlayer(), item); } +} - if (!autoCreate) { - return nullptr; +void Player::updateImpactTracker(CombatType_t type, int32_t amount) const { + if (client) { + client->sendUpdateImpactTracker(type, amount); } +} - std::shared_ptr<DepotChest> depotChest; - if (depotId > 0 && depotId < 18) { - depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_NULL + depotId); - } else if (depotId == 18) { - depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XVIII); - } else if (depotId == 19) { - depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XIX); - } else { - depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XX); +void Player::updateInputAnalyzer(CombatType_t type, int32_t amount, const std::string &target) const { + if (client) { + client->sendUpdateInputAnalyzer(type, amount, target); + } +} + +void Player::createLeaderTeamFinder(NetworkMessage &msg) const { + if (client) { + client->createLeaderTeamFinder(msg); + } +} + +void Player::sendLeaderTeamFinder(bool reset) const { + if (client) { + client->sendLeaderTeamFinder(reset); + } +} + +void Player::sendTeamFinderList() const { + if (client) { + client->sendTeamFinderList(); + } +} + +void Player::sendCreatureHelpers(uint32_t creatureId, uint16_t helpers) const { + if (client) { + client->sendCreatureHelpers(creatureId, helpers); + } +} + +void Player::setItemCustomPrice(uint16_t itemId, uint64_t price) { + itemPriceMap[itemId] = price; +} + +uint32_t Player::getCharmPoints() const { + return charmPoints; +} + +void Player::setCharmPoints(uint32_t points) { + charmPoints = points; +} + +bool Player::hasCharmExpansion() const { + return charmExpansion; +} + +void Player::setCharmExpansion(bool onOff) { + charmExpansion = onOff; +} + +void Player::setUsedRunesBit(int32_t bit) { + UsedRunesBit = bit; +} + +int32_t Player::getUsedRunesBit() const { + return UsedRunesBit; +} + +void Player::setUnlockedRunesBit(int32_t bit) { + UnlockedRunesBit = bit; +} + +int32_t Player::getUnlockedRunesBit() const { + return UnlockedRunesBit; +} + +void Player::setImmuneCleanse(ConditionType_t conditiontype) { + cleanseCondition.first = conditiontype; + cleanseCondition.second = OTSYS_TIME() + 10000; +} + +bool Player::isImmuneCleanse(ConditionType_t conditiontype) const { + const uint64_t timenow = OTSYS_TIME(); + if ((cleanseCondition.first == conditiontype) + && (timenow <= cleanseCondition.second)) { + return true; + } + return false; +} + +void Player::setImmuneFear() { + m_fearCondition.first = CONDITION_FEARED; + m_fearCondition.second = OTSYS_TIME() + 10000; +} + +bool Player::isImmuneFear() const { + const uint64_t timenow = OTSYS_TIME(); + return (m_fearCondition.first == CONDITION_FEARED) && (timenow <= m_fearCondition.second); +} + +uint16_t Player::parseRacebyCharm(charmRune_t charmId, bool set, uint16_t newRaceid) { + uint16_t raceid = 0; + switch (charmId) { + case CHARM_WOUND: + if (set) { + charmRuneWound = newRaceid; + } else { + raceid = charmRuneWound; + } + break; + case CHARM_ENFLAME: + if (set) { + charmRuneEnflame = newRaceid; + } else { + raceid = charmRuneEnflame; + } + break; + case CHARM_POISON: + if (set) { + charmRunePoison = newRaceid; + } else { + raceid = charmRunePoison; + } + break; + case CHARM_FREEZE: + if (set) { + charmRuneFreeze = newRaceid; + } else { + raceid = charmRuneFreeze; + } + break; + case CHARM_ZAP: + if (set) { + charmRuneZap = newRaceid; + } else { + raceid = charmRuneZap; + } + break; + case CHARM_CURSE: + if (set) { + charmRuneCurse = newRaceid; + } else { + raceid = charmRuneCurse; + } + break; + case CHARM_CRIPPLE: + if (set) { + charmRuneCripple = newRaceid; + } else { + raceid = charmRuneCripple; + } + break; + case CHARM_PARRY: + if (set) { + charmRuneParry = newRaceid; + } else { + raceid = charmRuneParry; + } + break; + case CHARM_DODGE: + if (set) { + charmRuneDodge = newRaceid; + } else { + raceid = charmRuneDodge; + } + break; + case CHARM_ADRENALINE: + if (set) { + charmRuneAdrenaline = newRaceid; + } else { + raceid = charmRuneAdrenaline; + } + break; + case CHARM_NUMB: + if (set) { + charmRuneNumb = newRaceid; + } else { + raceid = charmRuneNumb; + } + break; + case CHARM_CLEANSE: + if (set) { + charmRuneCleanse = newRaceid; + } else { + raceid = charmRuneCleanse; + } + break; + case CHARM_BLESS: + if (set) { + charmRuneBless = newRaceid; + } else { + raceid = charmRuneBless; + } + break; + case CHARM_SCAVENGE: + if (set) { + charmRuneScavenge = newRaceid; + } else { + raceid = charmRuneScavenge; + } + break; + case CHARM_GUT: + if (set) { + charmRuneGut = newRaceid; + } else { + raceid = charmRuneGut; + } + break; + case CHARM_LOW: + if (set) { + charmRuneLowBlow = newRaceid; + } else { + raceid = charmRuneLowBlow; + } + break; + case CHARM_DIVINE: + if (set) { + charmRuneDivine = newRaceid; + } else { + raceid = charmRuneDivine; + } + break; + case CHARM_VAMP: + if (set) { + charmRuneVamp = newRaceid; + } else { + raceid = charmRuneVamp; + } + break; + case CHARM_VOID: + if (set) { + charmRuneVoid = newRaceid; + } else { + raceid = charmRuneVoid; + } + break; + default: + raceid = 0; + break; + } + return raceid; +} + +bool Player::isNearDepotBox() { + const Position &pos = getPosition(); + for (int32_t cx = -1; cx <= 1; ++cx) { + for (int32_t cy = -1; cy <= 1; ++cy) { + const auto &posTile = g_game().map.getTile(static_cast<uint16_t>(pos.x + cx), static_cast<uint16_t>(pos.y + cy), pos.z); + if (!posTile) { + continue; + } + + if (posTile->hasFlag(TILESTATE_DEPOT)) { + return true; + } + } + } + return false; +} + +std::shared_ptr<DepotChest> Player::getDepotChest(uint32_t depotId, bool autoCreate) { + const auto it = depotChests.find(depotId); + if (it != depotChests.end()) { + return it->second; + } + + if (!autoCreate) { + return nullptr; + } + + std::shared_ptr<DepotChest> depotChest; + if (depotId > 0 && depotId < 18) { + depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_NULL + depotId); + } else if (depotId == 18) { + depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XVIII); + } else if (depotId == 19) { + depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XIX); + } else { + depotChest = std::make_shared<DepotChest>(ITEM_DEPOT_XX); } depotChests[depotId] = depotChest; @@ -1252,11 +1753,11 @@ std::shared_ptr<DepotChest> Player::getDepotChest(uint32_t depotId, bool autoCre } std::shared_ptr<DepotLocker> Player::getDepotLocker(uint32_t depotId) { - auto it = depotLockerMap.find(depotId); + const auto it = depotLockerMap.find(depotId); if (it != depotLockerMap.end()) { inbox->setParent(it->second); for (uint32_t i = g_configManager().getNumber(DEPOT_BOXES); i > 0; i--) { - if (std::shared_ptr<DepotChest> depotBox = getDepotChest(i, false)) { + if (const auto &depotBox = getDepotChest(i, false)) { depotBox->setParent(it->second->getItemByIndex(0)->getContainer()); } } @@ -1264,18 +1765,20 @@ std::shared_ptr<DepotLocker> Player::getDepotLocker(uint32_t depotId) { } // We need to make room for supply stash on 12+ protocol versions and remove it for 10x. - bool createSupplyStash = !client->oldProtocol; + const bool createSupplyStash = !client->oldProtocol; - std::shared_ptr<DepotLocker> depotLocker = std::make_shared<DepotLocker>(ITEM_LOCKER, createSupplyStash ? 4 : 3); + auto depotLocker = std::make_shared<DepotLocker>(ITEM_LOCKER, createSupplyStash ? 4 : 3); depotLocker->setDepotId(depotId); - depotLocker->internalAddThing(Item::CreateItem(ITEM_MARKET)); + const auto &marketItem = Item::CreateItem(ITEM_MARKET); + depotLocker->internalAddThing(marketItem); depotLocker->internalAddThing(inbox); if (createSupplyStash) { - depotLocker->internalAddThing(Item::CreateItem(ITEM_SUPPLY_STASH)); + const auto &supplyStashPtr = Item::CreateItem(ITEM_SUPPLY_STASH); + depotLocker->internalAddThing(supplyStashPtr); } - std::shared_ptr<Container> depotChest = Item::CreateItemAsContainer(ITEM_DEPOT, static_cast<uint16_t>(g_configManager().getNumber(DEPOT_BOXES))); + const auto &depotChest = Item::CreateItemAsContainer(ITEM_DEPOT, static_cast<uint16_t>(g_configManager().getNumber(DEPOT_BOXES))); for (uint32_t i = g_configManager().getNumber(DEPOT_BOXES); i > 0; i--) { - std::shared_ptr<DepotChest> depotBox = getDepotChest(i, true); + const auto &depotBox = getDepotChest(i, true); depotChest->internalAddThing(depotBox); depotBox->setParent(depotChest); } @@ -1294,7 +1797,7 @@ std::shared_ptr<RewardChest> Player::getRewardChest() { } std::shared_ptr<Reward> Player::getReward(const uint64_t rewardId, const bool autoCreate) { - auto it = rewardMap.find(rewardId); + const auto it = rewardMap.find(rewardId); if (it != rewardMap.end()) { return it->second; } @@ -1316,20 +1819,20 @@ void Player::removeReward(uint64_t rewardId) { void Player::getRewardList(std::vector<uint64_t> &rewards) const { rewards.reserve(rewardMap.size()); - for (auto &it : rewardMap) { - rewards.push_back(it.first); + for (const auto &[rewardId, snd] : rewardMap) { + rewards.emplace_back(rewardId); } } -std::vector<std::shared_ptr<Item>> Player::getRewardsFromContainer(std::shared_ptr<Container> container) const { +std::vector<std::shared_ptr<Item>> Player::getRewardsFromContainer(const std::shared_ptr<Container> &container) const { std::vector<std::shared_ptr<Item>> rewardItemsVector; if (container) { for (const auto &item : container->getItems(false)) { if (item->getID() == ITEM_REWARD_CONTAINER) { - auto items = getRewardsFromContainer(item->getContainer()); + const auto &items = getRewardsFromContainer(item->getContainer()); rewardItemsVector.insert(rewardItemsVector.end(), items.begin(), items.end()); } else { - rewardItemsVector.push_back(item); + rewardItemsVector.emplace_back(item); } } } @@ -1337,101 +1840,95 @@ std::vector<std::shared_ptr<Item>> Player::getRewardsFromContainer(std::shared_p return rewardItemsVector; } +void Player::sendCancelMessage(const std::string &msg) const { + if (client) { + client->sendTextMessage(TextMessage(MESSAGE_FAILURE, msg)); + } +} + void Player::sendCancelMessage(ReturnValue message) const { sendCancelMessage(getReturnMessage(message)); } -void Player::sendStats() { +void Player::sendCancelTarget() const { if (client) { - client->sendStats(); - lastStatsTrainingTime = getOfflineTrainingTime() / 60 / 1000; + client->sendCancelTarget(); } } -void Player::updateSupplyTracker(std::shared_ptr<Item> item) { - const auto &iType = Item::items.getItemType(item->getID()); - auto value = iType.buyPrice; - g_metrics().addCounter("player_supply", value, { { "player", getName() } }); - +void Player::sendCancelWalk() const { if (client) { - client->sendUpdateSupplyTracker(item); + client->sendCancelWalk(); } +} - if (m_party) { - m_party->addPlayerSupply(getPlayer(), item); +void Player::sendChangeSpeed(const std::shared_ptr<Creature> &creature, uint16_t newSpeed) const { + if (client) { + client->sendChangeSpeed(creature, newSpeed); } } -void Player::updateImpactTracker(CombatType_t type, int32_t amount) const { +void Player::sendCreatureHealth(const std::shared_ptr<Creature> &creature) const { if (client) { - client->sendUpdateImpactTracker(type, amount); + client->sendCreatureHealth(creature); } } -void Player::sendPing() { - int64_t timeNow = OTSYS_TIME(); - - bool hasLostConnection = false; - if ((timeNow - lastPing) >= 5000) { - lastPing = timeNow; - if (client) { - client->sendPing(); - } else { - hasLostConnection = true; - } +void Player::sendPartyCreatureUpdate(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendPartyCreatureUpdate(creature); } +} - int64_t noPongTime = timeNow - lastPong; - auto attackedCreature = getAttackedCreature(); - if ((hasLostConnection || noPongTime >= 7000) && attackedCreature && attackedCreature->getPlayer()) { - setAttackedCreature(nullptr); +void Player::sendPartyCreatureShield(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendPartyCreatureShield(creature); } +} - if (noPongTime >= 60000 && canLogout() && g_creatureEvents().playerLogout(static_self_cast<Player>())) { - g_logger().info("Player {} has been kicked due to ping timeout. (has client: {})", getName(), client != nullptr); - if (client) { - client->logout(true, true); - } else { - g_game().removeCreature(static_self_cast<Player>(), true); - } +void Player::sendPartyCreatureSkull(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendPartyCreatureSkull(creature); } } -std::shared_ptr<Item> Player::getWriteItem(uint32_t &retWindowTextId, uint16_t &retMaxWriteLen) { - retWindowTextId = this->windowTextId; - retMaxWriteLen = this->maxWriteLen; - return writeItem; +void Player::sendPartyCreatureHealth(const std::shared_ptr<Creature> &creature, uint8_t healthPercent) const { + if (client) { + client->sendPartyCreatureHealth(creature, healthPercent); + } } -void Player::setImbuingItem(std::shared_ptr<Item> item) { - imbuingItem = item; +void Player::sendPartyPlayerMana(const std::shared_ptr<Player> &player, uint8_t manaPercent) const { + if (client) { + client->sendPartyPlayerMana(player, manaPercent); + } } -void Player::setWriteItem(std::shared_ptr<Item> item, uint16_t maxWriteLength /*= 0*/) { - windowTextId++; +void Player::sendPartyCreatureShowStatus(const std::shared_ptr<Creature> &creature, bool showStatus) const { + if (client) { + client->sendPartyCreatureShowStatus(creature, showStatus); + } +} - if (item) { - writeItem = item; - this->maxWriteLen = maxWriteLength; - } else { - writeItem = nullptr; - this->maxWriteLen = 0; +void Player::sendPartyPlayerVocation(const std::shared_ptr<Player> &player) const { + if (client) { + client->sendPartyPlayerVocation(player); } } -std::shared_ptr<House> Player::getEditHouse(uint32_t &retWindowTextId, uint32_t &retListId) { - retWindowTextId = this->windowTextId; - retListId = this->editListId; - return editHouse; +void Player::sendPlayerVocation(const std::shared_ptr<Player> &player) const { + if (client) { + client->sendPlayerVocation(player); + } } -void Player::setEditHouse(std::shared_ptr<House> house, uint32_t listId /*= 0*/) { - windowTextId++; - editHouse = house; - editListId = listId; +void Player::sendDistanceShoot(const Position &from, const Position &to, uint16_t type) const { + if (client) { + client->sendDistanceShoot(from, to, type); + } } -void Player::sendHouseWindow(std::shared_ptr<House> house, uint32_t listId) const { +void Player::sendHouseWindow(const std::shared_ptr<House> &house, uint32_t listId) const { if (!client) { return; } @@ -1442,41 +1939,368 @@ void Player::sendHouseWindow(std::shared_ptr<House> house, uint32_t listId) cons } } -void Player::onApplyImbuement(Imbuement* imbuement, std::shared_ptr<Item> item, uint8_t slot, bool protectionCharm) { - if (!imbuement || !item) { - return; +void Player::sendCreatePrivateChannel(uint16_t channelId, const std::string &channelName) const { + if (client) { + client->sendCreatePrivateChannel(channelId, channelName); } +} - ImbuementInfo imbuementInfo; - if (item->getImbuementInfo(slot, &imbuementInfo)) { - g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, item already contains imbuement", this->getName()); - this->sendImbuementResult("An error ocurred, please reopen imbuement window."); - return; +void Player::sendClosePrivate(uint16_t channelId) { + if (channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY) { + g_chat().removeUserFromChannel(getPlayer(), channelId); } - const auto items = imbuement->getItems(); - for (auto &[key, value] : items) { - const ItemType &itemType = Item::items[key]; - if (static_self_cast<Player>()->getItemTypeCount(key) + this->getStashItemCount(itemType.id) < value) { - this->sendImbuementResult("You don't have all necessary items."); - return; - } + if (client) { + client->sendClosePrivate(channelId); } +} - const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID()); - if (!baseImbuement) { +void Player::sendIcons() { + if (!client) { return; } - uint32_t price = baseImbuement->price; - price += protectionCharm ? baseImbuement->protectionPrice : 0; - - if (!g_game().removeMoney(static_self_cast<Player>(), price, 0, true)) { - std::string message = fmt::format("You don't have {} gold coins.", price); + // Iterates over the Bakragore icons to check if the player has any + auto iconBakragore = IconBakragore::None; + for (const auto &icon : magic_enum::enum_values<IconBakragore>()) { + if (icon == IconBakragore::None) { + continue; + } - g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, player do not have money", this->getName()); - sendImbuementResult(message); - return; + const auto &condition = getCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, magic_enum::enum_integer(icon)); + if (condition) { + g_logger().debug("[{}] found active condition Bakragore with subId {}", __FUNCTION__, magic_enum::enum_integer(icon)); + iconBakragore = icon; + } + } + + // Remove the last icon so that Bakragore's is added + auto iconSet = getClientIcons(); + if (iconSet.size() >= 9 && iconBakragore != IconBakragore::None) { + std::vector<PlayerIcon> tempVector(iconSet.begin(), iconSet.end()); + tempVector.pop_back(); + iconSet = std::unordered_set<PlayerIcon>(tempVector.begin(), tempVector.end()); + } + + client->sendIcons(iconSet, iconBakragore); +} + +void Player::sendIconBakragore(IconBakragore icon) const { + if (client) { + client->sendIconBakragore(icon); + } +} + +void Player::removeBakragoreIcons() { + for (auto icon : magic_enum::enum_values<IconBakragore>()) { + if (hasCondition(CONDITION_BAKRAGORE, enumToValue(icon))) { + removeCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, true); + } + } +} + +void Player::removeBakragoreIcon(const IconBakragore icon) { + if (hasCondition(CONDITION_BAKRAGORE, enumToValue(icon))) { + removeCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, true); + } +} + +void Player::sendClientCheck() const { + if (client) { + client->sendClientCheck(); + } +} + +void Player::sendGameNews() const { + if (client) { + client->sendGameNews(); + } +} + +void Player::sendMagicEffect(const Position &pos, uint16_t type) const { + if (client) { + client->sendMagicEffect(pos, type); + } +} + +void Player::removeMagicEffect(const Position &pos, uint16_t type) const { + if (client) { + client->removeMagicEffect(pos, type); + } +} + +void Player::sendPing() { + const int64_t timeNow = OTSYS_TIME(); + + bool hasLostConnection = false; + if ((timeNow - lastPing) >= 5000) { + lastPing = timeNow; + if (client) { + client->sendPing(); + } else { + hasLostConnection = true; + } + } + + const int64_t noPongTime = timeNow - lastPong; + const auto &attackedCreature = getAttackedCreature(); + if ((hasLostConnection || noPongTime >= 7000) && attackedCreature && attackedCreature->getPlayer()) { + setAttackedCreature(nullptr); + } + + if (noPongTime >= 60000 && canLogout() && g_creatureEvents().playerLogout(static_self_cast<Player>())) { + g_logger().info("Player {} has been kicked due to ping timeout. (has client: {})", getName(), client != nullptr); + if (client) { + client->logout(true, true); + } else { + g_game().removeCreature(static_self_cast<Player>(), true); + } + } +} + +void Player::sendPingBack() const { + if (client) { + client->sendPingBack(); + } +} + +void Player::sendStats() { + if (client) { + client->sendStats(); + lastStatsTrainingTime = getOfflineTrainingTime() / 60 / 1000; + } +} + +void Player::sendBasicData() const { + if (client) { + client->sendBasicData(); + } +} + +void Player::sendBlessStatus() const { + if (client) { + client->sendBlessStatus(); + } +} + +void Player::sendSkills() const { + if (client) { + client->sendSkills(); + } +} + +void Player::sendTextMessage(MessageClasses mclass, const std::string &message) const { + if (client) { + client->sendTextMessage(TextMessage(mclass, message)); + } +} + +void Player::sendTextMessage(const TextMessage &message) const { + if (client) { + client->sendTextMessage(message); + } +} + +void Player::sendReLoginWindow(uint8_t unfairFightReduction) const { + if (client) { + client->sendReLoginWindow(unfairFightReduction); + } +} + +void Player::sendTextWindow(const std::shared_ptr<Item> &item, uint16_t maxlen, bool canWrite) const { + if (client) { + client->sendTextWindow(windowTextId, item, maxlen, canWrite); + } +} + +void Player::sendToChannel(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, uint16_t channelId) const { + if (client) { + client->sendToChannel(creature, type, text, channelId); + } +} + +void Player::sendShop(const std::shared_ptr<Npc> &npc) const { + if (client) { + client->sendShop(npc); + } +} + +void Player::sendSaleItemList(const std::map<uint16_t, uint16_t> &inventoryMap) const { + if (client && shopOwner) { + client->sendSaleItemList(shopOwner->getShopItemVector(getGUID()), inventoryMap); + } +} + +bool Player::hasImbuingItem() const { + return imbuingItem != nullptr; +} + +void Player::setImbuingItem(const std::shared_ptr<Item> &item) { + imbuingItem = item; +} + +void Player::addBlessing(uint8_t index, uint8_t count) { + if (blessings[index - 1] == 255) { + return; + } + + blessings[index - 1] += count; +} + +void Player::removeBlessing(uint8_t index, uint8_t count) { + if (blessings[index - 1] == 0) { + return; + } + + blessings[index - 1] -= count; +} + +bool Player::hasBlessing(uint8_t index) const { + return blessings[index - 1] != 0; +} + +void Player::sendCloseShop() const { + if (client) { + client->sendCloseShop(); + } +} + +void Player::sendMarketEnter(uint32_t depotId) const { + if (!client || this->getLastDepotId() == -1 || !depotId) { + return; + } + + client->sendMarketEnter(depotId); +} + +void Player::sendMarketLeave() { + inMarket = false; + if (client) { + client->sendMarketLeave(); + } +} + +void Player::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList &buyOffers, const MarketOfferList &sellOffers, uint8_t tier) const { + if (client) { + client->sendMarketBrowseItem(itemId, buyOffers, sellOffers, tier); + } +} + +void Player::sendMarketBrowseOwnOffers(const MarketOfferList &buyOffers, const MarketOfferList &sellOffers) const { + if (client) { + client->sendMarketBrowseOwnOffers(buyOffers, sellOffers); + } +} + +void Player::sendMarketBrowseOwnHistory(const HistoryMarketOfferList &buyOffers, const HistoryMarketOfferList &sellOffers) const { + if (client) { + client->sendMarketBrowseOwnHistory(buyOffers, sellOffers); + } +} + +void Player::sendMarketDetail(uint16_t itemId, uint8_t tier) const { + if (client) { + client->sendMarketDetail(itemId, tier); + } +} + +void Player::sendMarketAcceptOffer(const MarketOfferEx &offer) const { + if (client) { + client->sendMarketAcceptOffer(offer); + } +} + +void Player::sendMarketCancelOffer(const MarketOfferEx &offer) const { + if (client) { + client->sendMarketCancelOffer(offer); + } +} + +void Player::sendTradeItemRequest(const std::string &traderName, const std::shared_ptr<Item> &item, bool ack) const { + if (client) { + client->sendTradeItemRequest(traderName, item, ack); + } +} + +void Player::sendTradeClose() const { + if (client) { + client->sendCloseTrade(); + } +} + +void Player::sendWorldLight(LightInfo lightInfo) const { + if (client) { + client->sendWorldLight(lightInfo); + } +} + +void Player::sendTibiaTime(int32_t time) const { + if (client) { + client->sendTibiaTime(time); + } +} + +void Player::sendChannelsDialog() const { + if (client) { + client->sendChannelsDialog(); + } +} + +void Player::sendOpenPrivateChannel(const std::string &receiver) const { + if (client) { + client->sendOpenPrivateChannel(receiver); + } +} + +void Player::sendExperienceTracker(int64_t rawExp, int64_t finalExp) const { + if (client) { + client->sendExperienceTracker(rawExp, finalExp); + } +} + +void Player::sendOutfitWindow() const { + if (client) { + client->sendOutfitWindow(); + } +} + +// Imbuements + +void Player::onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr<Item> &item, uint8_t slot, bool protectionCharm) { + if (!imbuement || !item) { + return; + } + + ImbuementInfo imbuementInfo; + if (item->getImbuementInfo(slot, &imbuementInfo)) { + g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, item already contains imbuement", this->getName()); + this->sendImbuementResult("An error ocurred, please reopen imbuement window."); + return; + } + + const auto &items = imbuement->getItems(); + for (auto &[key, value] : items) { + const ItemType &itemType = Item::items[key]; + if (static_self_cast<Player>()->getItemTypeCount(key) + this->getStashItemCount(itemType.id) < value) { + this->sendImbuementResult("You don't have all necessary items."); + return; + } + } + + const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID()); + if (!baseImbuement) { + return; + } + + uint32_t price = baseImbuement->price; + price += protectionCharm ? baseImbuement->protectionPrice : 0; + + if (!g_game().removeMoney(static_self_cast<Player>(), price, 0, true)) { + const std::string message = fmt::format("You don't have {} gold coins.", price); + + g_logger().error("[Player::onApplyImbuement] - An error occurred while player with name {} try to apply imbuement, player do not have money", this->getName()); + sendImbuementResult(message); + return; } g_metrics().addCounter("balance_decrease", price, { { "player", getName() }, { "context", "apply_imbuement" } }); @@ -1484,7 +2308,7 @@ void Player::onApplyImbuement(Imbuement* imbuement, std::shared_ptr<Item> item, for (auto &[key, value] : items) { std::stringstream withdrawItemMessage; - uint32_t inventoryItemCount = getItemTypeCount(key); + const uint32_t inventoryItemCount = getItemTypeCount(key); if (inventoryItemCount >= value) { removeItemOfType(key, value, -1, true); continue; @@ -1518,7 +2342,7 @@ void Player::onApplyImbuement(Imbuement* imbuement, std::shared_ptr<Item> item, openImbuementWindow(item); } -void Player::onClearImbuement(std::shared_ptr<Item> item, uint8_t slot) { +void Player::onClearImbuement(const std::shared_ptr<Item> &item, uint8_t slot) { if (!item) { return; } @@ -1536,7 +2360,7 @@ void Player::onClearImbuement(std::shared_ptr<Item> item, uint8_t slot) { } if (!g_game().removeMoney(static_self_cast<Player>(), baseImbuement->removeCost, 0, true)) { - std::string message = fmt::format("You don't have {} gold coins.", baseImbuement->removeCost); + const std::string message = fmt::format("You don't have {} gold coins.", baseImbuement->removeCost); g_logger().error("[Player::onClearImbuement] - An error occurred while player with name {} try to apply imbuement, player do not have money", this->getName()); this->sendImbuementResult(message); @@ -1553,7 +2377,7 @@ void Player::onClearImbuement(std::shared_ptr<Item> item, uint8_t slot) { this->openImbuementWindow(item); } -void Player::openImbuementWindow(std::shared_ptr<Item> item) { +void Player::openImbuementWindow(const std::shared_ptr<Item> &item) { if (!client || !item) { return; } @@ -1563,7 +2387,7 @@ void Player::openImbuementWindow(std::shared_ptr<Item> item) { return; } - auto itemParent = item->getTopParent(); + const auto &itemParent = item->getTopParent(); if (itemParent && itemParent != getPlayer()) { this->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have to pick up the item to imbue it."); return; @@ -1572,212 +2396,7 @@ void Player::openImbuementWindow(std::shared_ptr<Item> item) { client->openImbuementWindow(item); } -void Player::sendSaleItemList(const std::map<uint16_t, uint16_t> &inventoryMap) const { - if (client && shopOwner) { - client->sendSaleItemList(shopOwner->getShopItemVector(getGUID()), inventoryMap); - } -} - -void Player::sendMarketEnter(uint32_t depotId) { - if (!client || this->getLastDepotId() == -1 || !depotId) { - return; - } - - client->sendMarketEnter(depotId); -} - -// container -void Player::sendAddContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> item) { - if (!client) { - return; - } - - if (!container) { - return; - } - - for (const auto &it : openContainers) { - const OpenContainer &openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - uint16_t slot = openContainer.index; - if (container->getID() == ITEM_BROWSEFIELD) { - uint16_t containerSize = container->size() - 1; - uint16_t pageEnd = openContainer.index + container->capacity() - 1; - if (containerSize > pageEnd) { - slot = pageEnd; - item = container->getItemByIndex(pageEnd); - } else { - slot = containerSize; - } - } else if (openContainer.index >= container->capacity()) { - item = container->getItemByIndex(openContainer.index - 1); - } - client->sendAddContainerItem(it.first, slot, item); - } -} - -void Player::sendUpdateContainerItem(std::shared_ptr<Container> container, uint16_t slot, std::shared_ptr<Item> newItem) { - if (!client) { - return; - } - - for (const auto &it : openContainers) { - const OpenContainer &openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - if (slot < openContainer.index) { - continue; - } - - uint16_t pageEnd = openContainer.index + container->capacity(); - if (slot >= pageEnd) { - continue; - } - - client->sendUpdateContainerItem(it.first, slot, newItem); - } -} - -void Player::sendRemoveContainerItem(std::shared_ptr<Container> container, uint16_t slot) { - if (!client) { - return; - } - - if (!container) { - return; - } - - for (auto &it : openContainers) { - OpenContainer &openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - uint16_t &firstIndex = openContainer.index; - if (firstIndex > 0 && firstIndex >= container->size() - 1) { - firstIndex -= container->capacity(); - sendContainer(it.first, container, false, firstIndex); - } - - client->sendRemoveContainerItem(it.first, std::max<uint16_t>(slot, firstIndex), container->getItemByIndex(container->capacity() + firstIndex)); - } -} - -void Player::onUpdateTileItem(std::shared_ptr<Tile> updateTile, const Position &pos, std::shared_ptr<Item> oldItem, const ItemType &oldType, std::shared_ptr<Item> newItem, const ItemType &newType) { - Creature::onUpdateTileItem(updateTile, pos, oldItem, oldType, newItem, newType); - - if (oldItem != newItem) { - onRemoveTileItem(updateTile, pos, oldType, oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - if (tradeItem && oldItem == tradeItem) { - g_game().internalCloseTrade(getPlayer()); - } - } -} - -void Player::onRemoveTileItem(std::shared_ptr<Tile> fromTile, const Position &pos, const ItemType &iType, std::shared_ptr<Item> item) { - Creature::onRemoveTileItem(fromTile, pos, iType, item); - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - std::shared_ptr<Container> container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - g_game().internalCloseTrade(static_self_cast<Player>()); - } - } - } - - checkLootContainers(item->getContainer()); -} - -void Player::onCreatureAppear(std::shared_ptr<Creature> creature, bool isLogin) { - Creature::onCreatureAppear(creature, isLogin); - - if (isLogin && creature == getPlayer()) { - onEquipInventory(); - - // Refresh bosstiary tracker onLogin - refreshCyclopediaMonsterTracker(true); - // Refresh bestiary tracker onLogin - refreshCyclopediaMonsterTracker(false); - - for (const auto &condition : storedConditionList) { - addCondition(condition); - } - storedConditionList.clear(); - - updateRegeneration(); - - std::shared_ptr<BedItem> bed = g_game().getBedBySleeper(guid); - if (bed) { - bed->wakeUp(static_self_cast<Player>()); - } - - auto version = client->oldProtocol ? getProtocolVersion() : CLIENT_VERSION; - g_logger().info("{} has logged in. (Protocol: {})", name, version); - - if (guild) { - guild->addMember(static_self_cast<Player>()); - } - - int32_t offlineTime; - if (getLastLogout() != 0) { - // Not counting more than 21 days to prevent overflow when multiplying with 1000 (for milliseconds). - offlineTime = std::min<int32_t>(time(nullptr) - getLastLogout(), 86400 * 21); - } else { - offlineTime = 0; - } - - for (const std::shared_ptr<Condition> &condition : getMuteConditions()) { - condition->setTicks(condition->getTicks() - (offlineTime * 1000)); - if (condition->getTicks() <= 0) { - removeCondition(condition); - } - } - - g_game().checkPlayersRecord(); - IOLoginData::updateOnlineStatus(guid, true); - if (getLevel() < g_configManager().getNumber(ADVENTURERSBLESSING_LEVEL) && getVocationId() > VOCATION_NONE) { - for (uint8_t i = 2; i <= 6; i++) { - if (!hasBlessing(i)) { - addBlessing(i, 1); - } - } - sendBlessStatus(); - } - - if (getCurrentMount() != 0) { - toggleMount(true); - } - - g_game().changePlayerSpeed(static_self_cast<Player>(), 0); - } -} - -void Player::onAttackedCreatureDisappear(bool isLogout) { - sendCancelTarget(); - - if (!isLogout) { - sendTextMessage(MESSAGE_FAILURE, "Target lost."); - } -} - -void Player::onFollowCreatureDisappear(bool isLogout) { - sendCancelTarget(); - - if (!isLogout) { - sendTextMessage(MESSAGE_FAILURE, "Target lost."); - } -} +// inventory void Player::onChangeZone(ZoneType_t zone) { if (zone == ZONE_PROTECTION) { @@ -1815,7 +2434,7 @@ void Player::onChangeZone(ZoneType_t zone) { } void Player::onAttackedCreatureChangeZone(ZoneType_t zone) { - auto attackedCreature = getAttackedCreature(); + const auto &attackedCreature = getAttackedCreature(); if (!attackedCreature) { return; } @@ -1840,49 +2459,7 @@ void Player::onAttackedCreatureChangeZone(ZoneType_t zone) { } } -void Player::onRemoveCreature(std::shared_ptr<Creature> creature, bool isLogout) { - Creature::onRemoveCreature(creature, isLogout); - - if (auto player = getPlayer(); player == creature) { - if (isLogout) { - onDeEquipInventory(); - - if (m_party) { - m_party->leaveParty(player, true); - } - if (guild) { - guild->removeMember(player); - } - - g_game().removePlayerUniqueLogin(player); - loginPosition = getPosition(); - lastLogout = time(nullptr); - g_logger().info("{} has logged out", getName()); - g_chat().removeUserFromAllChannels(player); - clearPartyInvitations(); - IOLoginData::updateOnlineStatus(guid, false); - } - - if (eventWalk != 0) { - setFollowCreature(nullptr); - } - - if (tradePartner) { - g_game().internalCloseTrade(player); - } - - closeShopWindow(); - - g_saveManager().savePlayer(player); - } - - if (creature == shopOwner) { - setShopOwner(nullptr); - sendCloseShop(); - } -} - -bool Player::openShopWindow(std::shared_ptr<Npc> npc, const std::vector<ShopBlock> &shopItems) { +bool Player::openShopWindow(const std::shared_ptr<Npc> &npc, const std::vector<ShopBlock> &shopItems) { Benchmark brenchmark; if (!npc) { g_logger().error("[Player::openShopWindow] - Npc is wrong or nullptr"); @@ -1920,11 +2497,11 @@ bool Player::closeShopWindow() { void Player::onWalk(Direction &dir) { if (hasCondition(CONDITION_FEARED)) { - Position pos = getNextPosition(dir, getPosition()); + const Position pos = getNextPosition(dir, getPosition()); - std::shared_ptr<Tile> tile = g_game().map.getTile(pos); + const auto &tile = g_game().map.getTile(pos); if (tile) { - std::shared_ptr<MagicField> field = tile->getFieldItem(); + const auto &field = tile->getFieldItem(); if (field && !field->isBlocking() && field->getDamage() != 0) { setNextActionTask(nullptr); setNextAction(OTSYS_TIME() + getStepDuration(dir)); @@ -1939,192 +2516,36 @@ void Player::onWalk(Direction &dir) { g_callbacks().executeCallback(EventCallback_t::playerOnWalk, &EventCallback::playerOnWalk, getPlayer(), dir); } -void Player::onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) { - Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - - const auto &followCreature = getFollowCreature(); - if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) { - isUpdatingPath = false; - g_game().updateCreatureWalk(getID()); // internally uses addEventWalk. - } - - if (creature != getPlayer()) { +void Player::checkTradeState(const std::shared_ptr<Item> &item) { + if (!tradeItem || tradeState == TRADE_TRANSFER) { return; } - if (tradeState != TRADE_TRANSFER) { - // check if we should close trade - if (tradeItem && !Position::areInRange<1, 1, 0>(tradeItem->getPosition(), getPosition())) { - g_game().internalCloseTrade(getPlayer()); - } - - if (tradePartner && !Position::areInRange<2, 2, 0>(tradePartner->getPosition(), getPosition())) { - g_game().internalCloseTrade(getPlayer()); - } - } - - // close modal windows - if (!modalWindows.empty()) { - // TODO: This shouldn't be hardcoded - for (uint32_t modalWindowId : modalWindows) { - if (modalWindowId == std::numeric_limits<uint32_t>::max()) { - sendTextMessage(MESSAGE_EVENT_ADVANCE, "Offline training aborted."); + if (tradeItem == item) { + g_game().internalCloseTrade(static_self_cast<Player>()); + } else { + auto container = std::dynamic_pointer_cast<Container>(item->getParent()); + while (container) { + if (container == tradeItem) { + g_game().internalCloseTrade(static_self_cast<Player>()); break; } + + container = std::dynamic_pointer_cast<Container>(container->getParent()); } - modalWindows.clear(); } +} - // leave market - if (inMarket) { - inMarket = false; - } - - if (m_party) { - m_party->updateSharedExperience(); - m_party->updatePlayerStatus(getPlayer(), oldPos, newPos); - } - - if (teleport || oldPos.z != newPos.z) { - int32_t ticks = g_configManager().getNumber(STAIRHOP_DELAY); - if (ticks > 0) { - if (const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks, 0)) { - addCondition(condition); - } - } - } -} - -void Player::onEquipInventory() { - for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { - std::shared_ptr<Item> item = inventory[slot]; - if (item) { - item->startDecaying(); - g_moveEvents().onPlayerEquip(getPlayer(), item, static_cast<Slots_t>(slot), false); - } - } -} - -void Player::onDeEquipInventory() { - for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { - std::shared_ptr<Item> item = inventory[slot]; - if (item) { - g_moveEvents().onPlayerDeEquip(getPlayer(), item, static_cast<Slots_t>(slot)); - } - } -} - -// container -void Player::onAddContainerItem(std::shared_ptr<Item> item) { - checkTradeState(item); -} - -void Player::onUpdateContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem) { - if (oldItem != newItem) { - onRemoveContainerItem(container, oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(oldItem); - } -} - -void Player::onRemoveContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> item) { - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - if (tradeItem->getParent() != container && container->isHoldingItem(tradeItem)) { - g_game().internalCloseTrade(static_self_cast<Player>()); - } - } - } - - checkLootContainers(item->getContainer()); -} - -void Player::onCloseContainer(std::shared_ptr<Container> container) { - if (!client) { - return; - } - - for (const auto &it : openContainers) { - if (it.second.container == container) { - client->sendCloseContainer(it.first); - } - } -} - -void Player::onSendContainer(std::shared_ptr<Container> container) { - if (!client || !container) { - return; - } - - bool hasParent = container->hasParent(); - for (const auto &it : openContainers) { - const OpenContainer &openContainer = it.second; - if (openContainer.container == container) { - client->sendContainer(it.first, container, hasParent, openContainer.index); - } - } -} - -// inventory -void Player::onUpdateInventoryItem(std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem) { - if (oldItem != newItem) { - onRemoveInventoryItem(oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(oldItem); - } -} - -void Player::onRemoveInventoryItem(std::shared_ptr<Item> item) { - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - std::shared_ptr<Container> container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - g_game().internalCloseTrade(static_self_cast<Player>()); - } - } - } - - checkLootContainers(item->getContainer()); -} - -void Player::checkTradeState(std::shared_ptr<Item> item) { - if (!tradeItem || tradeState == TRADE_TRANSFER) { - return; - } - - if (tradeItem == item) { - g_game().internalCloseTrade(static_self_cast<Player>()); - } else { - std::shared_ptr<Container> container = std::dynamic_pointer_cast<Container>(item->getParent()); - while (container) { - if (container == tradeItem) { - g_game().internalCloseTrade(static_self_cast<Player>()); - break; - } - - container = std::dynamic_pointer_cast<Container>(container->getParent()); - } - } -} - -void Player::setNextWalkActionTask(std::shared_ptr<Task> task) { - if (walkTaskEvent != 0) { - g_dispatcher().stopEvent(walkTaskEvent); - walkTaskEvent = 0; +void Player::setNextWalkActionTask(const std::shared_ptr<Task> &task) { + if (walkTaskEvent != 0) { + g_dispatcher().stopEvent(walkTaskEvent); + walkTaskEvent = 0; } walkTask = task; } -void Player::setNextWalkTask(std::shared_ptr<Task> task) { +void Player::setNextWalkTask(const std::shared_ptr<Task> &task) { if (nextStepEvent != 0) { g_dispatcher().stopEvent(nextStepEvent); nextStepEvent = 0; @@ -2136,7 +2557,7 @@ void Player::setNextWalkTask(std::shared_ptr<Task> task) { } } -void Player::setNextActionTask(std::shared_ptr<Task> task, bool resetIdleTime /*= true */) { +void Player::setNextActionTask(const std::shared_ptr<Task> &task, bool resetIdleTime /*= true */) { if (actionTaskEvent != 0) { g_dispatcher().stopEvent(actionTaskEvent); actionTaskEvent = 0; @@ -2154,7 +2575,7 @@ void Player::setNextActionTask(std::shared_ptr<Task> task, bool resetIdleTime /* } } -void Player::setNextActionPushTask(std::shared_ptr<Task> task) { +void Player::setNextActionPushTask(const std::shared_ptr<Task> &task) { if (actionTaskEventPush != 0) { g_dispatcher().stopEvent(actionTaskEventPush); actionTaskEventPush = 0; @@ -2165,7 +2586,7 @@ void Player::setNextActionPushTask(std::shared_ptr<Task> task) { } } -void Player::setNextPotionActionTask(std::shared_ptr<Task> task) { +void Player::setNextPotionActionTask(const std::shared_ptr<Task> &task) { if (actionPotionTaskEvent != 0) { g_dispatcher().stopEvent(actionPotionTaskEvent); actionPotionTaskEvent = 0; @@ -2179,6 +2600,17 @@ void Player::setNextPotionActionTask(std::shared_ptr<Task> task) { } } +void Player::setModuleDelay(uint8_t byteortype, int16_t delay) { + moduleDelayMap[byteortype] = OTSYS_TIME() + delay; +} + +bool Player::canRunModule(uint8_t byteortype) { + if (!moduleDelayMap[byteortype]) { + return true; + } + return moduleDelayMap[byteortype] <= OTSYS_TIME(); +} + uint32_t Player::getNextActionTime() const { return std::max<int64_t>(SCHEDULER_MINTICKS, nextAction - OTSYS_TIME()); } @@ -2187,129 +2619,379 @@ uint32_t Player::getNextPotionActionTime() const { return std::max<int64_t>(SCHEDULER_MINTICKS, nextPotionAction - OTSYS_TIME()); } -void Player::cancelPush() { - if (actionTaskEventPush != 0) { - g_dispatcher().stopEvent(actionTaskEventPush); - actionTaskEventPush = 0; - inEventMovePush = false; +std::shared_ptr<Item> Player::getWriteItem(uint32_t &retWindowTextId, uint16_t &retMaxWriteLen) { + retWindowTextId = this->windowTextId; + retMaxWriteLen = this->maxWriteLen; + return writeItem; +} + +void Player::setWriteItem(const std::shared_ptr<Item> &item, uint16_t maxWriteLength) { + windowTextId++; + + if (item) { + writeItem = item; + this->maxWriteLen = maxWriteLength; + } else { + writeItem = nullptr; + this->maxWriteLen = 0; } } -void Player::onThink(uint32_t interval) { - Creature::onThink(interval); +std::shared_ptr<House> Player::getEditHouse(uint32_t &retWindowTextId, uint32_t &retListId) { + retWindowTextId = this->windowTextId; + retListId = this->editListId; + return editHouse; +} - sendPing(); +void Player::setEditHouse(const std::shared_ptr<House> &house, uint32_t listId) { + windowTextId++; + editHouse = house; + editListId = listId; +} - MessageBufferTicks += interval; - if (MessageBufferTicks >= 1500) { - MessageBufferTicks = 0; - addMessageBuffer(); +void Player::learnInstantSpell(const std::string &spellName) { + if (!hasLearnedInstantSpell(spellName)) { + learnedInstantSpellList.emplace_back(spellName); } +} - // Transcendance (avatar trigger) - triggerTranscendance(); - // Momentum (cooldown resets) - triggerMomentum(); - auto playerTile = getTile(); - const bool vipStaysOnline = isVip() && g_configManager().getBoolean(VIP_STAY_ONLINE); - idleTime += interval; - if (playerTile && !playerTile->hasFlag(TILESTATE_NOLOGOUT) && !isAccessPlayer() && !isExerciseTraining() && !vipStaysOnline) { - const int32_t kickAfterMinutes = g_configManager().getNumber(KICK_AFTER_MINUTES); - if (idleTime > (kickAfterMinutes * 60000) + 60000) { - removePlayer(true); - } else if (client && idleTime == 60000 * kickAfterMinutes) { - std::ostringstream ss; - ss << "There was no variation in your behaviour for " << kickAfterMinutes << " minutes. You will be disconnected in one minute if there is no change in your actions until then."; - client->sendTextMessage(TextMessage(MESSAGE_ADMINISTRATOR, ss.str())); - } - } +void Player::forgetInstantSpell(const std::string &spellName) { + std::erase(learnedInstantSpellList, spellName); +} - if (g_game().getWorldType() != WORLD_TYPE_PVP_ENFORCED) { - checkSkullTicks(interval / 1000); +bool Player::hasLearnedInstantSpell(const std::string &spellName) const { + if (hasFlag(PlayerFlags_t::CannotUseSpells)) { + return false; } - addOfflineTrainingTime(interval); - if (lastStatsTrainingTime != getOfflineTrainingTime() / 60 / 1000) { - sendStats(); + if (hasFlag(PlayerFlags_t::IgnoreSpellCheck)) { + return true; } - // Wheel of destiny major spells - wheel()->onThink(); - - g_callbacks().executeCallback(EventCallback_t::playerOnThink, &EventCallback::playerOnThink, getPlayer(), interval); + return std::ranges::any_of(learnedInstantSpellList, [&](const auto &learnedSpellName) { + return strcasecmp(learnedSpellName.c_str(), spellName.c_str()) == 0; + }); } -uint32_t Player::isMuted() const { - if (hasFlag(PlayerFlags_t::CannotBeMuted)) { - return 0; +void Player::updateRegeneration() const { + if (!vocation) { + return; } - int32_t muteTicks = 0; - for (const std::shared_ptr<Condition> &condition : conditions) { - if (condition->getType() == CONDITION_MUTED && condition->getTicks() > muteTicks) { - muteTicks = condition->getTicks(); - } + const auto &condition = getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); + if (condition) { + condition->setParam(CONDITION_PARAM_HEALTHGAIN, vocation->getHealthGainAmount()); + condition->setParam(CONDITION_PARAM_HEALTHTICKS, vocation->getHealthGainTicks()); + condition->setParam(CONDITION_PARAM_MANAGAIN, vocation->getManaGainAmount()); + condition->setParam(CONDITION_PARAM_MANATICKS, vocation->getManaGainTicks()); } - return static_cast<uint32_t>(muteTicks) / 1000; } -void Player::addMessageBuffer() { - if (MessageBufferCount > 0 && g_configManager().getNumber(MAX_MESSAGEBUFFER) != 0 && !hasFlag(PlayerFlags_t::CannotBeMuted)) { - --MessageBufferCount; - } +void Player::setScheduledSaleUpdate(bool scheduled) { + scheduledSaleUpdate = scheduled; } -void Player::removeMessageBuffer() { - if (hasFlag(PlayerFlags_t::CannotBeMuted)) { - return; - } - - const int32_t maxMessageBuffer = g_configManager().getNumber(MAX_MESSAGEBUFFER); - if (maxMessageBuffer != 0 && MessageBufferCount <= maxMessageBuffer + 1) { - if (++MessageBufferCount > maxMessageBuffer) { - uint32_t muteCount = 1; - auto it = muteCountMap.find(guid); - if (it != muteCountMap.end()) { - muteCount = it->second; - } +bool Player::getScheduledSaleUpdate() const { + return scheduledSaleUpdate; +} - uint32_t muteTime = 5 * muteCount * muteCount; - muteCountMap[guid] = muteCount + 1; - std::shared_ptr<Condition> condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_MUTED, muteTime * 1000, 0); - addCondition(condition); +bool Player::inPushEvent() const { + return inEventMovePush; +} - std::ostringstream ss; - ss << "You are muted for " << muteTime << " seconds."; - sendTextMessage(MESSAGE_FAILURE, ss.str()); - } - } +void Player::pushEvent(bool b) { + inEventMovePush = b; } -void Player::drainHealth(std::shared_ptr<Creature> attacker, int32_t damage) { - if (PLAYER_SOUND_HEALTH_CHANGE >= static_cast<uint32_t>(uniform_random(1, 100))) { - g_game().sendSingleSoundEffect(static_self_cast<Player>()->getPosition(), sex == PLAYERSEX_FEMALE ? SoundEffect_t::HUMAN_FEMALE_BARK : SoundEffect_t::HUMAN_MALE_BARK, getPlayer()); +bool Player::walkExhausted() const { + if (hasCondition(CONDITION_PARALYZE)) { + return lastWalking > OTSYS_TIME(); } - Creature::drainHealth(attacker, damage); - sendStats(); + return false; } -void Player::drainMana(std::shared_ptr<Creature> attacker, int32_t manaLoss) { - Creature::drainMana(attacker, manaLoss); - sendStats(); +void Player::setWalkExhaust(int64_t value) { + lastWalking = OTSYS_TIME() + value; } -void Player::addManaSpent(uint64_t amount) { - if (hasFlag(PlayerFlags_t::NotGainMana)) { - return; - } +const std::map<uint8_t, OpenContainer> &Player::getOpenContainers() const { + return openContainers; +} - uint64_t currReqMana = vocation->getReqMana(magLevel); - uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); - if (currReqMana >= nextReqMana) { - // player has reached max magic level - return; - } +uint16_t Player::getBaseXpGain() const { + return baseXpGain; +} + +void Player::setBaseXpGain(uint16_t value) { + baseXpGain = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); +} + +uint16_t Player::getVoucherXpBoost() const { + return voucherXpBoost; +} + +void Player::setVoucherXpBoost(uint16_t value) { + voucherXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); +} + +uint16_t Player::getGrindingXpBoost() const { + return grindingXpBoost; +} + +uint16_t Player::getDisplayGrindingXpBoost() const { + return std::clamp<uint16_t>(grindingXpBoost * (baseXpGain / 100), 0, std::numeric_limits<uint16_t>::max()); +} + +void Player::setGrindingXpBoost(uint16_t value) { + grindingXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); +} + +uint16_t Player::getXpBoostPercent() const { + return xpBoostPercent; +} + +uint16_t Player::getDisplayXpBoostPercent() const { + return std::clamp<uint16_t>(xpBoostPercent * (baseXpGain / 100), 0, std::numeric_limits<uint16_t>::max()); +} + +void Player::setXpBoostPercent(uint16_t percent) { + xpBoostPercent = percent; +} + +uint16_t Player::getStaminaXpBoost() const { + return staminaXpBoost; +} + +void Player::setStaminaXpBoost(uint16_t value) { + staminaXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); +} + +void Player::setXpBoostTime(uint16_t timeLeft) { + // only allow time boosts of 12 hours or less + if (timeLeft > 12 * 3600) { + xpBoostTime = 12 * 3600; + return; + } + xpBoostTime = timeLeft; +} + +uint16_t Player::getXpBoostTime() const { + return xpBoostTime; +} + +int32_t Player::getIdleTime() const { + return idleTime; +} + +void Player::setTraining(bool value) { + for (const auto &[key, player] : g_game().getPlayers()) { + if (!this->isInGhostMode() || player->isAccessPlayer()) { + player->vip()->notifyStatusChange(static_self_cast<Player>(), value ? VipStatus_t::Training : VipStatus_t::Online, false); + } + } + vip()->setStatus(VipStatus_t::Training); + setExerciseTraining(value); +} + +void Player::addItemImbuementStats(const Imbuement* imbuement) { + bool requestUpdate = false; + // Check imbuement skills + for (int32_t skill = SKILL_FIRST; skill <= SKILL_LAST; ++skill) { + if (imbuement->skills[skill]) { + requestUpdate = true; + setVarSkill(static_cast<skills_t>(skill), imbuement->skills[skill]); + } + } + + // Check imbuement magic level + for (int32_t stat = STAT_FIRST; stat <= STAT_LAST; ++stat) { + if (imbuement->stats[stat]) { + requestUpdate = true; + setVarStats(static_cast<stats_t>(stat), imbuement->stats[stat]); + } + } + + // Add imbuement speed + if (imbuement->speed != 0) { + g_game().changeSpeed(static_self_cast<Player>(), imbuement->speed); + } + + // Add imbuement capacity + if (imbuement->capacity != 0) { + requestUpdate = true; + bonusCapacity = (capacity * imbuement->capacity) / 100; + } + + if (requestUpdate) { + sendStats(); + sendSkills(); + } +} + +void Player::removeItemImbuementStats(const Imbuement* imbuement) { + if (!imbuement) { + return; + } + + bool requestUpdate = false; + + for (int32_t skill = SKILL_FIRST; skill <= SKILL_LAST; ++skill) { + if (imbuement->skills[skill]) { + requestUpdate = true; + setVarSkill(static_cast<skills_t>(skill), -imbuement->skills[skill]); + } + } + + // Check imbuement magic level + for (int32_t stat = STAT_FIRST; stat <= STAT_LAST; ++stat) { + if (imbuement->stats[stat]) { + requestUpdate = true; + setVarStats(static_cast<stats_t>(stat), -imbuement->stats[stat]); + } + } + + // Remove imbuement speed + if (imbuement->speed != 0) { + g_game().changeSpeed(static_self_cast<Player>(), -imbuement->speed); + } + + // Remove imbuement capacity + if (imbuement->capacity != 0) { + requestUpdate = true; + bonusCapacity = 0; + } + + if (requestUpdate) { + sendStats(); + sendSkills(); + } +} + +void Player::updateImbuementTrackerStats() const { + if (imbuementTrackerWindowOpen) { + g_game().playerRequestInventoryImbuements(getID(), true); + } +} + +// User Interface action exhaustion + +bool Player::isUIExhausted(uint32_t exhaustionTime) const { + return (OTSYS_TIME() - lastUIInteraction < exhaustionTime); +} + +void Player::updateUIExhausted() { + lastUIInteraction = OTSYS_TIME(); +} + +bool Player::isQuickLootListedItem(const std::shared_ptr<Item> &item) const { + if (!item) { + return false; + } + + auto it = std::ranges::find(quickLootListItemIds, item->getID()); + return it != quickLootListItemIds.end(); +} + +void Player::setNextAction(int64_t time) { + if (time > nextAction) { + nextAction = time; + } +} + +bool Player::canDoAction() const { + return nextAction <= OTSYS_TIME(); +} + +void Player::setNextPotionAction(int64_t time) { + if (time > nextPotionAction) { + nextPotionAction = time; + } +} + +bool Player::canDoPotionAction() const { + return nextPotionAction <= OTSYS_TIME(); +} + +void Player::cancelPush() { + if (actionTaskEventPush != 0) { + g_dispatcher().stopEvent(actionTaskEventPush); + actionTaskEventPush = 0; + inEventMovePush = false; + } +} + +uint32_t Player::isMuted() const { + if (hasFlag(PlayerFlags_t::CannotBeMuted)) { + return 0; + } + + int32_t muteTicks = 0; + for (const auto &condition : conditions) { + if (condition->getType() == CONDITION_MUTED && condition->getTicks() > muteTicks) { + muteTicks = condition->getTicks(); + } + } + return static_cast<uint32_t>(muteTicks) / 1000; +} + +void Player::addMessageBuffer() { + if (MessageBufferCount > 0 && g_configManager().getNumber(MAX_MESSAGEBUFFER) != 0 && !hasFlag(PlayerFlags_t::CannotBeMuted)) { + --MessageBufferCount; + } +} + +void Player::removeMessageBuffer() { + if (hasFlag(PlayerFlags_t::CannotBeMuted)) { + return; + } + + const int32_t maxMessageBuffer = g_configManager().getNumber(MAX_MESSAGEBUFFER); + if (maxMessageBuffer != 0 && MessageBufferCount <= maxMessageBuffer + 1) { + if (++MessageBufferCount > maxMessageBuffer) { + uint32_t muteCount = 1; + const auto it = muteCountMap.find(guid); + if (it != muteCountMap.end()) { + muteCount = it->second; + } + + const uint32_t muteTime = 5 * muteCount * muteCount; + muteCountMap[guid] = muteCount + 1; + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_MUTED, muteTime * 1000, 0); + addCondition(condition); + + std::ostringstream ss; + ss << "You are muted for " << muteTime << " seconds."; + sendTextMessage(MESSAGE_FAILURE, ss.str()); + } + } +} + +void Player::drainHealth(const std::shared_ptr<Creature> &attacker, int32_t damage) { + if (PLAYER_SOUND_HEALTH_CHANGE >= static_cast<uint32_t>(uniform_random(1, 100))) { + g_game().sendSingleSoundEffect(static_self_cast<Player>()->getPosition(), sex == PLAYERSEX_FEMALE ? SoundEffect_t::HUMAN_FEMALE_BARK : SoundEffect_t::HUMAN_MALE_BARK, getPlayer()); + } + + Creature::drainHealth(attacker, damage); + sendStats(); +} + +void Player::drainMana(const std::shared_ptr<Creature> &attacker, int32_t manaLoss) { + Creature::drainMana(attacker, manaLoss); + sendStats(); +} + +void Player::addManaSpent(uint64_t amount) { + if (hasFlag(PlayerFlags_t::NotGainMana)) { + return; + } + + uint64_t currReqMana = vocation->getReqMana(magLevel); + uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); + if (currReqMana >= nextReqMana) { + // player has reached max magic level + return; + } g_events().eventPlayerOnGainSkillTries(static_self_cast<Player>(), SKILL_MAGLEVEL, amount); g_callbacks().executeCallback(EventCallback_t::playerOnGainSkillTries, &EventCallback::playerOnGainSkillTries, getPlayer(), SKILL_MAGLEVEL, amount); @@ -2342,7 +3024,7 @@ void Player::addManaSpent(uint64_t amount) { manaSpent += amount; - uint8_t oldPercent = magLevelPercent; + const uint8_t oldPercent = magLevelPercent; if (nextReqMana > currReqMana) { magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana); } else { @@ -2359,9 +3041,9 @@ void Player::addManaSpent(uint64_t amount) { } } -void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool sendText /* = false*/) { - uint64_t currLevelExp = Player::getExpForLevel(level); - uint64_t nextLevelExp = Player::getExpForLevel(level + 1); +void Player::addExperience(const std::shared_ptr<Creature> &target, uint64_t exp, bool sendText /* = false*/) { + uint64_t currLevelExp = getExpForLevel(level); + uint64_t nextLevelExp = getExpForLevel(level + 1); uint64_t rawExp = exp; if (currLevelExp >= nextLevelExp) { // player has reached max level @@ -2377,8 +3059,8 @@ void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool return; } - auto rate = exp / rawExp; - std::map<std::string, std::string> attrs({ { "player", getName() }, { "level", std::to_string(getLevel()) }, { "rate", std::to_string(rate) } }); + const auto rate = exp / rawExp; + const std::map<std::string, std::string> attrs({ { "player", getName() }, { "level", std::to_string(getLevel()) }, { "rate", std::to_string(rate) } }); if (sendText) { g_metrics().addCounter("player_experience_raw", rawExp, attrs); g_metrics().addCounter("player_experience_actual", exp, attrs); @@ -2388,8 +3070,8 @@ void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool } // Hazard system experience - std::shared_ptr<Monster> monster = target && target->getMonster() ? target->getMonster() : nullptr; - bool handleHazardExperience = monster && monster->getHazard() && getHazardSystemPoints() > 0; + const auto &monster = target && target->getMonster() ? target->getMonster() : nullptr; + const bool handleHazardExperience = monster && monster->getHazard() && getHazardSystemPoints() > 0; if (handleHazardExperience) { exp += (exp * (1.75 * getHazardSystemPoints() * g_configManager().getFloat(HAZARD_EXP_BONUS_MULTIPLIER))) / 100.; } @@ -2416,13 +3098,13 @@ void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool if (!spectators.empty()) { message.type = MESSAGE_EXPERIENCE_OTHERS; message.text = getName() + " gained " + expString; - for (const std::shared_ptr<Creature> &spectator : spectators) { + for (const auto &spectator : spectators) { spectator->getPlayer()->sendTextMessage(message); } } } - uint32_t prevLevel = level; + const uint32_t prevLevel = level; while (experience >= nextLevelExp) { ++level; // Player stats gain for vocations level <= 8 @@ -2442,7 +3124,7 @@ void Player::addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool } currLevelExp = nextLevelExp; - nextLevelExp = Player::getExpForLevel(level + 1); + nextLevelExp = getExpForLevel(level + 1); if (currLevelExp >= nextLevelExp) { // player has reached max level break; @@ -2497,7 +3179,7 @@ void Player::removeExperience(uint64_t exp, bool sendText /* = false*/) { if (sendText) { lostExp -= experience; - std::string expString = fmt::format("You lost {} experience point{}.", lostExp, (lostExp != 1 ? "s" : "")); + const std::string expString = fmt::format("You lost {} experience point{}.", lostExp, (lostExp != 1 ? "s" : "")); TextMessage message(MESSAGE_EXPERIENCE, expString); message.position = position; @@ -2510,13 +3192,13 @@ void Player::removeExperience(uint64_t exp, bool sendText /* = false*/) { if (!spectators.empty()) { message.type = MESSAGE_EXPERIENCE_OTHERS; message.text = getName() + " lost " + expString; - for (const std::shared_ptr<Creature> &spectator : spectators) { + for (const auto &spectator : spectators) { spectator->getPlayer()->sendTextMessage(message); } } } - uint32_t oldLevel = level; + const uint32_t oldLevel = level; uint64_t currLevelExp = Player::getExpForLevel(level); while (level > 1 && experience < currLevelExp) { @@ -2555,7 +3237,7 @@ void Player::removeExperience(uint64_t exp, bool sendText /* = false*/) { sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); } - uint64_t nextLevelExp = Player::getExpForLevel(level + 1); + const uint64_t nextLevelExp = Player::getExpForLevel(level + 1); if (nextLevelExp > currLevelExp) { levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp); } else { @@ -2570,7 +3252,7 @@ double_t Player::getPercentLevel(uint64_t count, uint64_t nextLevelCount) { return 0; } - double_t result = round(((count * 100.) / nextLevelCount) * 100.) / 100.; + const double_t result = round(((count * 100.) / nextLevelCount) * 100.) / 100.; if (result > 100) { return 0; } @@ -2587,11 +3269,11 @@ void Player::onBlockHit() { } } -void Player::onTakeDamage(std::shared_ptr<Creature> attacker, int32_t damage) { +void Player::onTakeDamage(const std::shared_ptr<Creature> &attacker, int32_t damage) { // nothing here yet } -void Player::onAttackedCreatureBlockHit(BlockType_t blockType) { +void Player::onAttackedCreatureBlockHit(const BlockType_t &blockType) { lastAttackBlockType = blockType; switch (blockType) { @@ -2622,19 +3304,23 @@ void Player::onAttackedCreatureBlockHit(BlockType_t blockType) { } bool Player::hasShield() const { - std::shared_ptr<Item> item = inventory[CONST_SLOT_LEFT]; - if (item && item->getWeaponType() == WEAPON_SHIELD) { + const auto &itemLeft = inventory[CONST_SLOT_LEFT]; + if (itemLeft && itemLeft->getWeaponType() == WEAPON_SHIELD) { return true; } - item = inventory[CONST_SLOT_RIGHT]; - if (item && item->getWeaponType() == WEAPON_SHIELD) { + const auto &itemRight = inventory[CONST_SLOT_RIGHT]; + if (itemRight && itemRight->getWeaponType() == WEAPON_SHIELD) { return true; } return false; } -BlockType_t Player::blockHit(std::shared_ptr<Creature> attacker, CombatType_t combatType, int32_t &damage, bool checkDefense /* = false*/, bool checkArmor /* = false*/, bool field /* = false*/) { +bool Player::isPzLocked() const { + return pzLocked; +} + +BlockType_t Player::blockHit(const std::shared_ptr<Creature> &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense, bool checkArmor, bool field) { BlockType_t blockType = Creature::blockHit(attacker, combatType, damage, checkDefense, checkArmor, field); if (attacker) { sendCreatureSquare(attacker, SQ_COLOR_BLACK); @@ -2650,43 +3336,47 @@ BlockType_t Player::blockHit(std::shared_ptr<Creature> attacker, CombatType_t co continue; } - std::shared_ptr<Item> item = inventory[slot]; + const auto &item = inventory[slot]; if (!item) { continue; } + for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { + ImbuementInfo imbuementInfo; + if (!item->getImbuementInfo(slotid, &imbuementInfo)) { + continue; + } + + const int16_t &imbuementAbsorbPercent = imbuementInfo.imbuement->absorbPercent[combatTypeToIndex(combatType)]; + + if (imbuementAbsorbPercent != 0) { + damage -= std::ceil(damage * (imbuementAbsorbPercent / 100.)); + } + } + + // const ItemType &it = Item::items[item->getID()]; if (it.abilities) { + int totalAbsorbPercent = 0; const int16_t &absorbPercent = it.abilities->absorbPercent[combatTypeToIndex(combatType)]; - auto charges = item->getAttribute<uint16_t>(ItemAttribute_t::CHARGES); if (absorbPercent != 0) { - damage -= std::round(damage * (absorbPercent / 100.)); - if (charges != 0) { - g_game().transformItem(item, item->getID(), charges - 1); - } + totalAbsorbPercent += absorbPercent; } if (field) { const int16_t &fieldAbsorbPercent = it.abilities->fieldAbsorbPercent[combatTypeToIndex(combatType)]; if (fieldAbsorbPercent != 0) { - damage -= std::round(damage * (fieldAbsorbPercent / 100.)); - if (charges != 0) { - g_game().transformItem(item, item->getID(), charges - 1); - } + totalAbsorbPercent += fieldAbsorbPercent; } } - } - - for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { - ImbuementInfo imbuementInfo; - if (!item->getImbuementInfo(slotid, &imbuementInfo)) { - continue; - } - const int16_t &imbuementAbsorbPercent = imbuementInfo.imbuement->absorbPercent[combatTypeToIndex(combatType)]; + if (totalAbsorbPercent > 0) { + damage -= std::round(damage * (totalAbsorbPercent / 100.0)); - if (imbuementAbsorbPercent != 0) { - damage -= std::ceil(damage * (imbuementAbsorbPercent / 100.)); + const auto charges = item->getAttribute<uint16_t>(ItemAttribute_t::CHARGES); + if (charges != 0) { + g_game().transformItem(item, item->getID(), charges - 1); + } } } } @@ -2703,37 +3393,94 @@ BlockType_t Player::blockHit(std::shared_ptr<Creature> attacker, CombatType_t co return blockType; } -void Player::death(std::shared_ptr<Creature> lastHitCreature) { - if (!g_configManager().getBoolean(TOGGLE_MOUNT_IN_PZ) && isMounted()) { - dismount(); - g_game().internalCreatureChangeOutfit(getPlayer(), defaultOutfit); +void Player::doAttacking(uint32_t interval) { + if (lastAttack == 0) { + lastAttack = OTSYS_TIME() - getAttackSpeed() - 1; + } + + if (hasCondition(CONDITION_PACIFIED)) { + return; + } + + const auto &attackedCreature = getAttackedCreature(); + if (!attackedCreature) { + return; + } + + if ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()) { + bool result = false; + + const auto &tool = getWeapon(); + const auto &weapon = g_weapons().getWeapon(tool); + uint32_t delay = getAttackSpeed(); + bool classicSpeed = g_configManager().getBoolean(CLASSIC_ATTACK_SPEED); + + if (weapon) { + if (!weapon->interruptSwing()) { + result = weapon->useWeapon(static_self_cast<Player>(), tool, attackedCreature); + } else if (!classicSpeed && !canDoAction()) { + delay = getNextActionTime(); + } else { + result = weapon->useWeapon(static_self_cast<Player>(), tool, attackedCreature); + } + } else if (hasWeaponDistanceEquipped()) { + return; + } else { + result = Weapon::useFist(static_self_cast<Player>(), attackedCreature); + } + + const auto &task = createPlayerTask( + std::max<uint32_t>(SCHEDULER_MINTICKS, delay), + [playerId = getID()] { g_game().checkCreatureAttack(playerId); }, + __FUNCTION__ + ); + + if (!classicSpeed) { + setNextActionTask(task, false); + } else { + g_dispatcher().scheduleEvent(task); + } + + if (result) { + updateLastAggressiveAction(); + updateLastAttack(); + } + } +} + +void Player::death(const std::shared_ptr<Creature> &lastHitCreature) { + if (!g_configManager().getBoolean(TOGGLE_MOUNT_IN_PZ) && isMounted()) { + dismount(); + g_game().internalCreatureChangeOutfit(getPlayer(), defaultOutfit); } loginPosition = town->getTemplePosition(); g_game().sendSingleSoundEffect(static_self_cast<Player>()->getPosition(), sex == PLAYERSEX_FEMALE ? SoundEffect_t::HUMAN_FEMALE_DEATH : SoundEffect_t::HUMAN_MALE_DEATH, getPlayer()); if (skillLoss) { - uint8_t unfairFightReduction = 100; int playerDmg = 0; int othersDmg = 0; uint32_t sumLevels = 0; uint32_t inFightTicks = 5 * 60 * 1000; - for (const auto &it : damageMap) { - CountBlock_t cb = it.second; - if ((OTSYS_TIME() - cb.ticks) <= inFightTicks) { - std::shared_ptr<Player> damageDealer = g_game().getPlayerByID(it.first); + for (const auto &[creatureId, damageInfo] : damageMap) { + const auto &[total, ticks] = damageInfo; + if ((OTSYS_TIME() - ticks) <= inFightTicks) { + const auto &damageDealer = g_game().getPlayerByID(creatureId); if (damageDealer) { - playerDmg += cb.total; + playerDmg += total; sumLevels += damageDealer->getLevel(); } else { - othersDmg += cb.total; + othersDmg += total; } } } + bool pvpDeath = false; if (playerDmg > 0 || othersDmg > 0) { pvpDeath = (Player::lastHitIsPlayer(lastHitCreature) || playerDmg / (playerDmg + static_cast<double>(othersDmg)) >= 0.05); } + + uint8_t unfairFightReduction = 100; if (pvpDeath && sumLevels > level) { double reduce = level / static_cast<double>(sumLevels); unfairFightReduction = std::max<uint8_t>(20, std::floor((reduce * 100) + 0.5)); @@ -2743,7 +3490,7 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { uint64_t sumMana = 0; uint64_t lostMana = 0; - // sum up all the mana + // Sum up all the mana for (uint32_t i = 1; i <= magLevel; ++i) { sumMana += vocation->getReqMana(i); } @@ -2753,12 +3500,10 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { double deathLossPercent = getLostPercent() * (unfairFightReduction / 100.); // Charm bless bestiary - if (lastHitCreature && lastHitCreature->getMonster()) { - if (charmRuneBless != 0) { - const auto mType = g_monsters().getMonsterType(lastHitCreature->getName()); - if (mType && mType->info.raceid == charmRuneBless) { - deathLossPercent = (deathLossPercent * 90) / 100; - } + if (lastHitCreature && lastHitCreature->getMonster() && charmRuneBless != 0) { + const auto &mType = g_monsters().getMonsterType(lastHitCreature->getName()); + if (mType && mType->info.raceid == charmRuneBless) { + deathLossPercent = (deathLossPercent * 90) / 100; } } @@ -2780,7 +3525,9 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { } // Level loss - uint64_t expLoss = static_cast<uint64_t>(experience * deathLossPercent); + auto expLoss = static_cast<uint64_t>(std::ceil(experience * deathLossPercent)); + g_logger().debug("[{}] - experience lost {}", __FUNCTION__, expLoss); + g_events().eventPlayerOnLoseExperience(static_self_cast<Player>(), expLoss); g_callbacks().executeCallback(EventCallback_t::playerOnLoseExperience, &EventCallback::playerOnLoseExperience, getPlayer(), expLoss); @@ -2789,15 +3536,15 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { lostExp << "You lost " << expLoss << " experience."; // Skill loss - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { // for each skill + for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { // For each skill uint64_t sumSkillTries = 0; - for (uint16_t c = 11; c <= skills[i].level; ++c) { // sum up all required tries for all skill levels + for (uint16_t c = 11; c <= skills[i].level; ++c) { // Sum up all required tries for all skill levels sumSkillTries += vocation->getReqSkillTries(i, c); } sumSkillTries += skills[i].tries; - uint32_t lostSkillTries = static_cast<uint32_t>(sumSkillTries * deathLossPercent); + auto lostSkillTries = static_cast<uint32_t>(sumSkillTries * deathLossPercent); while (lostSkillTries > skills[i].tries) { lostSkillTries -= skills[i].tries; @@ -2867,14 +3614,21 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { bless.empty() ? blessOutput << "You weren't protected with any blessings." : blessOutput << "You were blessed with " << bless; - // Make player lose bless + const auto playerSkull = getSkull(); + bool hasSkull = (playerSkull == Skulls_t::SKULL_RED || playerSkull == Skulls_t::SKULL_BLACK); uint8_t maxBlessing = 8; - if (pvpDeath && hasBlessing(1)) { + if (!hasSkull && pvpDeath && hasBlessing(1)) { removeBlessing(1, 1); // Remove TOF only } else { for (int i = 2; i <= maxBlessing; i++) { removeBlessing(i, 1); } + + const auto &playerAmulet = getThing(CONST_SLOT_NECKLACE); + bool usingAol = (playerAmulet && playerAmulet->getItem()->getID() == ITEM_AMULETOFLOSS); + if (usingAol) { + removeItemOfType(ITEM_AMULETOFLOSS, 1, -1); + } } } sendTextMessage(MESSAGE_EVENT_ADVANCE, blessOutput.str()); @@ -2893,7 +3647,7 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { auto it = conditions.begin(), end = conditions.end(); while (it != end) { - std::shared_ptr<Condition> condition = *it; + auto condition = *it; // isSupress block to delete spells conditions (ensures that the player cannot, for example, reset the cooldown time of the familiar and summon several) if (condition->isPersistent() && condition->isRemovableOnDeath()) { it = conditions.erase(it); @@ -2910,7 +3664,7 @@ void Player::death(std::shared_ptr<Creature> lastHitCreature) { auto it = conditions.begin(), end = conditions.end(); while (it != end) { - std::shared_ptr<Condition> condition = *it; + auto condition = *it; if (condition->isPersistent()) { it = conditions.erase(it); @@ -2940,7 +3694,7 @@ bool Player::spawn() { return false; } - auto spectators = Spectators().find<Creature>(position, true); + const auto &spectators = Spectators().find<Creature>(position, true); for (const auto &spectator : spectators) { if (const auto &tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendCreatureAppear(static_self_cast<Player>(), pos, true); @@ -2972,18 +3726,18 @@ void Player::despawn() { Game::removeCreatureCheck(static_self_cast<Player>()); // remove from map - std::shared_ptr<Tile> tile = getTile(); + const auto &tile = getTile(); if (!tile) { return; } std::vector<int32_t> oldStackPosVector; - auto spectators = Spectators().find<Creature>(tile->getPosition(), true); + const auto &spectators = Spectators().find<Creature>(tile->getPosition(), true); size_t i = 0; for (const auto &spectator : spectators) { if (const auto &player = spectator->getPlayer()) { - oldStackPosVector.push_back(player->canSeeCreature(static_self_cast<Player>()) ? tile->getStackposOfCreature(player, getPlayer()) : -1); + oldStackPosVector.emplace_back(player->canSeeCreature(static_self_cast<Player>()) ? tile->getStackposOfCreature(player, getPlayer()) : -1); } if (const auto &player = spectator->getPlayer()) { player->sendRemoveTileThing(tile->getPosition(), oldStackPosVector[i++]); @@ -3006,7 +3760,7 @@ void Player::despawn() { setDead(true); } -bool Player::dropCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_ptr<Creature> mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) { +bool Player::dropCorpse(const std::shared_ptr<Creature> &lastHitCreature, const std::shared_ptr<Creature> &mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) { if (getZoneType() != ZONE_PVP || !Player::lastHitIsPlayer(lastHitCreature)) { return Creature::dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); } @@ -3015,8 +3769,8 @@ bool Player::dropCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_p return false; } -std::shared_ptr<Item> Player::getCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_ptr<Creature> mostDamageCreature) { - std::shared_ptr<Item> corpse = Creature::getCorpse(lastHitCreature, mostDamageCreature); +std::shared_ptr<Item> Player::getCorpse(const std::shared_ptr<Creature> &lastHitCreature, const std::shared_ptr<Creature> &mostDamageCreature) { + const auto &corpse = Creature::getCorpse(lastHitCreature, mostDamageCreature); if (corpse && corpse->getContainer()) { std::ostringstream ss; if (lastHitCreature) { @@ -3046,13 +3800,13 @@ void Player::addInFightTicks(bool pzlock /*= false*/) { updateImbuementTrackerStats(); - // this method can be called asynchronously. - g_dispatcher().context().tryAddEvent([self = std::weak_ptr<Player>(getPlayer())] { - if (const auto &player = self.lock()) { - player->addCondition(Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(PZ_LOCKED), 0)); - } - }, - "Player::addInFightTicks"); + safeCall([this] { + addCondition(Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(PZ_LOCKED), 0)); + }); +} + +void Player::setDailyReward(uint8_t reward) { + this->isDailyReward = reward; } void Player::removeList() { @@ -3080,30 +3834,27 @@ void Player::removePlayer(bool displayEffect, bool forced /*= true*/) { } } -// close container and its child containers -void Player::autoCloseContainers(std::shared_ptr<Container> container) { - std::vector<uint32_t> closeList; - for (const auto &it : openContainers) { - std::shared_ptr<Container> tmpContainer = it.second.container; - while (tmpContainer) { - if (tmpContainer->isRemoved() || tmpContainer == container) { - closeList.push_back(it.first); - break; - } +uint64_t Player::getExpForLevel(const uint32_t level) { + return (((level - 6ULL) * level + 17ULL) * level - 12ULL) / 6ULL * 100ULL; +} - tmpContainer = std::dynamic_pointer_cast<Container>(tmpContainer->getParent()); - } +uint16_t Player::getStaminaMinutes() const { + return staminaMinutes; +} + +void Player::sendItemsPrice() const { + if (client) { + client->sendItemsPrice(); } +} - for (uint32_t containerId : closeList) { - closeContainer(containerId); - if (client) { - client->sendCloseContainer(containerId); - } +void Player::sendForgingData() const { + if (client) { + client->sendForgingData(); } } -bool Player::hasCapacity(std::shared_ptr<Item> item, uint32_t count) const { +bool Player::hasCapacity(const std::shared_ptr<Item> &item, uint32_t count) const { if (hasFlag(PlayerFlags_t::CannotPickupItem)) { return false; } @@ -3119,8 +3870,8 @@ bool Player::hasCapacity(std::shared_ptr<Item> item, uint32_t count) const { return itemWeight <= getFreeCapacity(); } -ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature>) { - std::shared_ptr<Item> item = thing->getItem(); +ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &) { + const auto &item = thing->getItem(); if (item == nullptr) { g_logger().error("[Player::queryAdd] - Item is nullptr"); return RETURNVALUE_NOTPOSSIBLE; @@ -3129,10 +3880,10 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, return RETURNVALUE_ITEMISNOTYOURS; } - bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); + const bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); if (childIsOwner) { // a child container is querying the player, just check if enough capacity - bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); + const bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); if (skipLimit || hasCapacity(item, count)) { return RETURNVALUE_NOERROR; } @@ -3194,7 +3945,7 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, if (item->getWeaponType() != WEAPON_SHIELD && !item->isQuiver()) { ret = RETURNVALUE_CANNOTBEDRESSED; } else { - std::shared_ptr<Item> leftItem = inventory[CONST_SLOT_LEFT]; + const auto &leftItem = inventory[CONST_SLOT_LEFT]; if (leftItem) { if ((leftItem->getSlotPosition() | slotPosition) & SLOTP_TWO_HAND) { if (item->isQuiver() && leftItem->getWeaponType() == WEAPON_DISTANCE) { @@ -3212,12 +3963,12 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, } else if (slotPosition & SLOTP_TWO_HAND) { ret = RETURNVALUE_CANNOTBEDRESSED; } else if (inventory[CONST_SLOT_LEFT]) { - std::shared_ptr<Item> leftItem = inventory[CONST_SLOT_LEFT]; - WeaponType_t type = item->getWeaponType(), leftType = leftItem->getWeaponType(); - - if (leftItem->getSlotPosition() & SLOTP_TWO_HAND) { + const auto &leftItem = inventory[CONST_SLOT_LEFT]; + const WeaponType_t type = item->getWeaponType(); + const WeaponType_t leftType = leftItem ? leftItem->getWeaponType() : WEAPON_NONE; + if (leftItem && leftItem->getSlotPosition() & SLOTP_TWO_HAND) { ret = RETURNVALUE_DROPTWOHANDEDITEM; - } else if (item == leftItem && count == item->getItemCount()) { + } else if (leftItem && item == leftItem && count == item->getItemCount()) { ret = RETURNVALUE_NOERROR; } else if (leftType == WEAPON_SHIELD && type == WEAPON_SHIELD) { ret = RETURNVALUE_CANONLYUSEONESHIELD; @@ -3237,7 +3988,7 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, ret = RETURNVALUE_CANNOTBEDRESSED; } else if (slotPosition & SLOTP_TWO_HAND) { if (inventory[CONST_SLOT_RIGHT]) { - WeaponType_t type = item->getWeaponType(); + const WeaponType_t type = item->getWeaponType(); // Allow equip bow when quiver is in SLOT_RIGHT if (type == WEAPON_DISTANCE && inventory[CONST_SLOT_RIGHT]->isQuiver()) { ret = RETURNVALUE_NOERROR; @@ -3248,19 +3999,20 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, ret = RETURNVALUE_NOERROR; } } else if (slotPosition & SLOTP_LEFT) { - WeaponType_t type = item->getWeaponType(); + const WeaponType_t type = item->getWeaponType(); if (type == WEAPON_NONE || type == WEAPON_SHIELD || type == WEAPON_AMMO) { ret = RETURNVALUE_CANNOTBEDRESSED; } else { ret = RETURNVALUE_NOERROR; } } else if (inventory[CONST_SLOT_RIGHT]) { - std::shared_ptr<Item> rightItem = inventory[CONST_SLOT_RIGHT]; - WeaponType_t type = item->getWeaponType(), rightType = rightItem->getWeaponType(); + const auto &rightItem = inventory[CONST_SLOT_RIGHT]; + const WeaponType_t type = item->getWeaponType(); + const WeaponType_t rightType = rightItem ? rightItem->getWeaponType() : WEAPON_NONE; - if (rightItem->getSlotPosition() & SLOTP_TWO_HAND) { + if (rightItem && rightItem->getSlotPosition() & SLOTP_TWO_HAND) { ret = RETURNVALUE_DROPTWOHANDEDITEM; - } else if (item == rightItem && count == item->getItemCount()) { + } else if (rightItem && item == rightItem && count == item->getItemCount()) { ret = RETURNVALUE_NOERROR; } else if (rightType == WEAPON_SHIELD && type == WEAPON_SHIELD) { ret = RETURNVALUE_CANONLYUSEONESHIELD; @@ -3319,7 +4071,7 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, if (ret == RETURNVALUE_NOERROR || ret == RETURNVALUE_NOTENOUGHROOM) { // need an exchange with source? - std::shared_ptr<Item> inventoryItem = getInventoryItem(static_cast<Slots_t>(index)); + const auto &inventoryItem = getInventoryItem(static_cast<Slots_t>(index)); if (inventoryItem && (!inventoryItem->isStackable() || inventoryItem->getID() != item->getID())) { return RETURNVALUE_NEEDEXCHANGE; } @@ -3338,7 +4090,7 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, } ReturnValue Player::queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) { - auto item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { maxQueryCount = 0; return RETURNVALUE_NOTPOSSIBLE; @@ -3347,23 +4099,23 @@ ReturnValue Player::queryMaxCount(int32_t index, const std::shared_ptr<Thing> &t if (index == INDEX_WHEREEVER) { uint32_t n = 0; for (int32_t slotIndex = CONST_SLOT_FIRST; slotIndex <= CONST_SLOT_LAST; ++slotIndex) { - std::shared_ptr<Item> inventoryItem = inventory[slotIndex]; + const auto &inventoryItem = inventory[slotIndex]; if (inventoryItem) { - if (std::shared_ptr<Container> subContainer = inventoryItem->getContainer()) { + if (const auto &subContainer = inventoryItem->getContainer()) { uint32_t queryCount = 0; subContainer->queryMaxCount(INDEX_WHEREEVER, item, item->getItemCount(), queryCount, flags); n += queryCount; // iterate through all items, including sub-containers (deep search) for (ContainerIterator it = subContainer->iterator(); it.hasNext(); it.advance()) { - if (std::shared_ptr<Container> tmpContainer = (*it)->getContainer()) { + if (const auto &tmpContainer = (*it)->getContainer()) { queryCount = 0; tmpContainer->queryMaxCount(INDEX_WHEREEVER, item, item->getItemCount(), queryCount, flags); n += queryCount; } } } else if (inventoryItem->isStackable() && item->equals(inventoryItem) && inventoryItem->getItemCount() < inventoryItem->getStackSize()) { - uint32_t remainder = (inventoryItem->getStackSize() - inventoryItem->getItemCount()); + const uint32_t remainder = (inventoryItem->getStackSize() - inventoryItem->getItemCount()); if (queryAdd(slotIndex, item, remainder, flags) == RETURNVALUE_NOERROR) { n += remainder; @@ -3382,7 +4134,7 @@ ReturnValue Player::queryMaxCount(int32_t index, const std::shared_ptr<Thing> &t } else { std::shared_ptr<Item> destItem = nullptr; - std::shared_ptr<Thing> destThing = getThing(index); + const auto &destThing = getThing(index); if (destThing) { destItem = destThing->getItem(); } @@ -3406,18 +4158,17 @@ ReturnValue Player::queryMaxCount(int32_t index, const std::shared_ptr<Thing> &t if (maxQueryCount < count) { return RETURNVALUE_NOTENOUGHROOM; - } else { - return RETURNVALUE_NOERROR; } + return RETURNVALUE_NOERROR; } -ReturnValue Player::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> /*= nullptr*/) { - int32_t index = getThingIndex(thing); +ReturnValue Player::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> & /*= nullptr */) { + const int32_t index = getThingIndex(thing); if (index == -1) { return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return RETURNVALUE_NOTPOSSIBLE; } @@ -3433,17 +4184,17 @@ ReturnValue Player::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t co return RETURNVALUE_NOERROR; } -std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) { +std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) { if (index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER) { - *destItem = nullptr; + destItem = nullptr; - std::shared_ptr<Item> item = thing->getItem(); - if (item == nullptr) { + const auto &item = thing->getItem(); + if (!item) { return getPlayer(); } - bool autoStack = !((flags & FLAG_IGNOREAUTOSTACK) == FLAG_IGNOREAUTOSTACK); - bool isStackable = item->isStackable(); + const bool autoStack = !(flags & FLAG_IGNOREAUTOSTACK); + const bool isStackable = item->isStackable(); std::vector<std::shared_ptr<Container>> containers; @@ -3463,20 +4214,20 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh if (queryAdd(slotIndex, item, item->getItemCount(), 0) == RETURNVALUE_NOERROR) { if (inventoryItem->equals(item) && inventoryItem->getItemCount() < inventoryItem->getStackSize()) { index = slotIndex; - *destItem = inventoryItem; + destItem = inventoryItem; return getPlayer(); } } - if (std::shared_ptr<Container> subContainer = inventoryItem->getContainer()) { + if (const auto &subContainer = inventoryItem->getContainer()) { containers.push_back(subContainer); } - } else if (std::shared_ptr<Container> subContainer = inventoryItem->getContainer()) { + } else if (const auto &subContainer = inventoryItem->getContainer()) { containers.push_back(subContainer); } } else if (queryAdd(slotIndex, item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { // empty slot index = slotIndex; - *destItem = nullptr; + destItem = nullptr; return getPlayer(); } } @@ -3490,15 +4241,15 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh while (n) { if (tmpContainer->queryAdd(tmpContainer->capacity() - n, item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { index = tmpContainer->capacity() - n; - *destItem = nullptr; + destItem = nullptr; return tmpContainer; } n--; } - for (const std::shared_ptr<Item> &tmpContainerItem : tmpContainer->getItemList()) { - if (std::shared_ptr<Container> subContainer = tmpContainerItem->getContainer()) { + for (const auto &tmpContainerItem : tmpContainer->getItemList()) { + if (const auto &subContainer = tmpContainerItem->getContainer()) { containers.push_back(subContainer); } } @@ -3520,11 +4271,11 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh // try find an already existing item to stack with if (tmpItem->equals(item) && tmpItem->getItemCount() < tmpItem->getStackSize()) { index = n; - *destItem = tmpItem; + destItem = tmpItem; return tmpContainer; } - if (std::shared_ptr<Container> subContainer = tmpItem->getContainer()) { + if (const auto &subContainer = tmpItem->getContainer()) { containers.push_back(subContainer); } @@ -3533,7 +4284,7 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh if (n < tmpContainer->capacity() && tmpContainer->queryAdd(n, item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { index = n; - *destItem = nullptr; + destItem = nullptr; return tmpContainer; } } @@ -3543,11 +4294,11 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh std::shared_ptr<Thing> destThing = getThing(index); if (destThing) { - *destItem = destThing->getItem(); + destItem = destThing->getItem(); } std::shared_ptr<Item> item = thing->getItem(); - bool movingAmmoToQuiver = item && *destItem && (*destItem)->isQuiver() && item->isAmmo(); + bool movingAmmoToQuiver = item && destItem && destItem->isQuiver() && item->isAmmo(); // force shield any slot right to player cylinder if (index == CONST_SLOT_RIGHT && !movingAmmoToQuiver) { return getPlayer(); @@ -3556,14 +4307,14 @@ std::shared_ptr<Cylinder> Player::queryDestination(int32_t &index, const std::sh std::shared_ptr<Cylinder> subCylinder = std::dynamic_pointer_cast<Cylinder>(destThing); if (subCylinder) { index = INDEX_WHEREEVER; - *destItem = nullptr; + destItem = nullptr; return subCylinder; } else { return getPlayer(); } } -void Player::addThing(int32_t index, std::shared_ptr<Thing> thing) { +void Player::addThing(int32_t index, const std::shared_ptr<Thing> &thing) { if (!thing) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -3572,7 +4323,7 @@ void Player::addThing(int32_t index, std::shared_ptr<Thing> thing) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -3584,13 +4335,13 @@ void Player::addThing(int32_t index, std::shared_ptr<Thing> thing) { sendInventoryItem(static_cast<Slots_t>(index), item); } -void Player::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) { +void Player::updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) { int32_t index = getThingIndex(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -3605,17 +4356,17 @@ void Player::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t onUpdateInventoryItem(item, item); } -void Player::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { +void Player::replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) { if (index > CONST_SLOT_LAST) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> oldItem = getInventoryItem(static_cast<Slots_t>(index)); + const auto &oldItem = getInventoryItem(static_cast<Slots_t>(index)); if (!oldItem) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -3631,8 +4382,8 @@ void Player::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { inventory[index] = item; } -void Player::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { - std::shared_ptr<Item> item = thing->getItem(); +void Player::removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) { + const auto &item = thing->getItem(); if (!item) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -3653,7 +4404,7 @@ void Player::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { item->resetParent(); inventory[index] = nullptr; } else { - uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count)); + const auto newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count)); item->setItemCount(newCount); // send change to client @@ -3674,7 +4425,7 @@ void Player::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { } } -int32_t Player::getThingIndex(std::shared_ptr<Thing> thing) const { +int32_t Player::getThingIndex(const std::shared_ptr<Thing> &thing) const { for (uint8_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { if (inventory[i] == thing) { return i; @@ -3694,7 +4445,7 @@ size_t Player::getLastIndex() const { uint32_t Player::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const { uint32_t count = 0; for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (!item) { continue; } @@ -3703,7 +4454,7 @@ uint32_t Player::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) con count += Item::countByType(item, subType); } - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const auto &container = item->getContainer()) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { if ((*it)->getID() == itemId) { count += Item::countByType(*it, subType); @@ -3714,17 +4465,21 @@ uint32_t Player::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) con return count; } -void Player::stashContainer(StashContainerList itemDict) { +void Player::stashContainer(const StashContainerList &itemDict) { StashItemList stashItemDict; // ItemID - Count - for (const auto &it_dict : itemDict) { - stashItemDict[(it_dict.first)->getID()] = it_dict.second; + for (const auto &[item, itemCount] : itemDict) { + if (!item) { + continue; + } + + stashItemDict[item->getID()] = itemCount; } - for (auto it : stashItems) { - if (!stashItemDict[it.first]) { - stashItemDict[it.first] = it.second; + for (const auto &[itemId, itemCount] : stashItems) { + if (!stashItemDict[itemId]) { + stashItemDict[itemId] = itemCount; } else { - stashItemDict[it.first] += it.second; + stashItemDict[itemId] += itemCount; } } @@ -3736,11 +4491,14 @@ void Player::stashContainer(StashContainerList itemDict) { uint32_t totalStowed = 0; std::ostringstream retString; uint16_t refreshDepotSearchOnItem = 0; - for (const auto &stashIterator : itemDict) { - uint16_t iteratorCID = (stashIterator.first)->getID(); - if (g_game().internalRemoveItem(stashIterator.first, stashIterator.second) == RETURNVALUE_NOERROR) { - addItemOnStash(iteratorCID, stashIterator.second); - totalStowed += stashIterator.second; + for (const auto &[item, itemCount] : itemDict) { + if (!item) { + continue; + } + const uint16_t iteratorCID = item->getID(); + if (g_game().internalRemoveItem(item, itemCount) == RETURNVALUE_NOERROR) { + addItemOnStash(iteratorCID, itemCount); + totalStowed += itemCount; if (isDepotSearchOpenOnItem(iteratorCID)) { refreshDepotSearchOnItem = iteratorCID; } @@ -3765,7 +4523,7 @@ void Player::stashContainer(StashContainerList itemDict) { } } -bool Player::removeItemOfType(uint16_t itemId, uint32_t amount, int32_t subType, bool ignoreEquipped /* = false*/) { +bool Player::removeItemOfType(uint16_t itemId, uint32_t amount, int32_t subType, bool ignoreEquipped /* = false*/) const { if (amount == 0) { return true; } @@ -3774,41 +4532,41 @@ bool Player::removeItemOfType(uint16_t itemId, uint32_t amount, int32_t subType, uint32_t count = 0; for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (!item) { continue; } if (!ignoreEquipped && item->getID() == itemId) { - uint32_t itemCount = Item::countByType(item, subType); + const uint32_t itemCount = Item::countByType(item, subType); if (itemCount == 0) { continue; } - itemList.push_back(item); + itemList.emplace_back(item); count += itemCount; if (count >= amount) { - g_game().internalRemoveItems(std::move(itemList), amount, Item::items[itemId].stackable); + g_game().internalRemoveItems(itemList, amount, Item::items[itemId].stackable); return true; } - } else if (std::shared_ptr<Container> container = item->getContainer()) { + } else if (const auto &container = item->getContainer()) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> containerItem = *it; + const auto &containerItem = *it; if (containerItem->getID() == itemId) { - uint32_t itemCount = Item::countByType(containerItem, subType); + const uint32_t itemCount = Item::countByType(containerItem, subType); if (itemCount == 0) { continue; } - itemList.push_back(containerItem); + itemList.emplace_back(containerItem); count += itemCount; - auto stackable = Item::items[itemId].stackable; + const auto stackable = Item::items[itemId].stackable; // If the amount of items in the backpack is equal to or greater than the amount // It will remove items and stop the iteration if (count >= amount) { - g_game().internalRemoveItems(std::move(itemList), amount, stackable); + g_game().internalRemoveItems(itemList, amount, stackable); return true; } } @@ -3832,7 +4590,7 @@ bool Player::hasItemCountById(uint16_t itemId, uint32_t itemAmount, bool checkSt // Check items from stash for (StashItemList stashToSend = getStashItems(); - auto [stashItemId, itemCount] : stashToSend) { + const auto &[stashItemId, itemCount] : stashToSend) { if (!checkStash) { break; } @@ -3877,10 +4635,84 @@ bool Player::removeItemCountById(uint16_t itemId, uint32_t itemAmount, bool remo return false; } +void Player::addItemOnStash(uint16_t itemId, uint32_t amount) { + const auto it = stashItems.find(itemId); + if (it != stashItems.end()) { + stashItems[itemId] += amount; + return; + } + + stashItems[itemId] = amount; +} + +uint32_t Player::getStashItemCount(uint16_t itemId) const { + const auto it = stashItems.find(itemId); + if (it != stashItems.end()) { + return it->second; + } + return 0; +} + +bool Player::withdrawItem(uint16_t itemId, uint32_t amount) { + const auto it = stashItems.find(itemId); + if (it != stashItems.end()) { + if (it->second > amount) { + stashItems[itemId] -= amount; + } else if (it->second == amount) { + stashItems.erase(itemId); + } else { + return false; + } + return true; + } + return false; +} + +StashItemList Player::getStashItems() const { + return stashItems; +} + +uint32_t Player::getBaseCapacity() const { + if (hasFlag(PlayerFlags_t::CannotPickupItem)) { + return 0; + } + if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { + return std::numeric_limits<uint32_t>::max(); + } + return capacity; +} + +uint32_t Player::getCapacity() const { + if (hasFlag(PlayerFlags_t::CannotPickupItem)) { + return 0; + } + if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { + return std::numeric_limits<uint32_t>::max(); + } + return capacity + bonusCapacity + varStats[STAT_CAPACITY] + (m_wheelPlayer->getStat(WheelStat_t::CAPACITY) * 100); +} + +uint32_t Player::getBonusCapacity() const { + if (hasFlag(PlayerFlags_t::CannotPickupItem) || hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { + return std::numeric_limits<uint32_t>::max(); + } + return bonusCapacity; +} + +uint32_t Player::getFreeCapacity() const { + if (hasFlag(PlayerFlags_t::CannotPickupItem)) { + return 0; + } else if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { + return std::numeric_limits<uint32_t>::max(); + } else { + return std::max<int32_t>(0, getCapacity() - inventoryWeight); + } +} + ItemsTierCountList Player::getInventoryItemsId(bool ignoreStoreInbox /* false */) const { ItemsTierCountList itemMap; for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (!item) { continue; } @@ -3902,92 +4734,277 @@ ItemsTierCountList Player::getInventoryItemsId(bool ignoreStoreInbox /* false */ return itemMap; } -std::vector<std::shared_ptr<Item>> Player::getInventoryItemsFromId(uint16_t itemId, bool ignore /*= true*/) const { - std::vector<std::shared_ptr<Item>> itemVector; - for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; - if (!item) { - continue; - } - - if (!ignore && item->getID() == itemId) { - itemVector.push_back(item); - } +/******************************************************************************* + * Hazard system + ******************************************************************************/ +// Parser - if (std::shared_ptr<Container> container = item->getContainer()) { - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - auto containerItem = *it; - if (containerItem->getID() == itemId) { - itemVector.push_back(containerItem); - } - } - } +void Player::parseAttackRecvHazardSystem(CombatDamage &damage, const std::shared_ptr<Monster> &monster) { + if (!monster || !monster->getHazard()) { + return; } - return itemVector; -} + if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { + return; + } -std::array<double_t, COMBAT_COUNT> Player::getFinalDamageReduction() const { - std::array<double_t, COMBAT_COUNT> combatReductionArray; - combatReductionArray.fill(0); - calculateDamageReductionFromEquipedItems(combatReductionArray); - for (int combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) { - combatReductionArray[combatTypeIndex] = std::clamp<double_t>( - std::floor(combatReductionArray[combatTypeIndex]), - -100., - 100. - ); + if (damage.primary.type == COMBAT_HEALING) { + return; } - return combatReductionArray; -} -void Player::calculateDamageReductionFromEquipedItems(std::array<double_t, COMBAT_COUNT> &combatReductionArray) const { - for (uint8_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { - std::shared_ptr<Item> item = inventory[slot]; - if (item) { - calculateDamageReductionFromItem(combatReductionArray, item); + auto points = getHazardSystemPoints(); + if (m_party) { + for (const auto &partyMember : m_party->getMembers()) { + if (partyMember && partyMember->getHazardSystemPoints() < points) { + points = partyMember->getHazardSystemPoints(); + } + } + + if (m_party->getLeader() && m_party->getLeader()->getHazardSystemPoints() < points) { + points = m_party->getLeader()->getHazardSystemPoints(); } } -} -void Player::calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionArray, std::shared_ptr<Item> item) const { - for (uint16_t combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) { - updateDamageReductionFromItemImbuement(combatReductionArray, item, combatTypeIndex); - updateDamageReductionFromItemAbility(combatReductionArray, item, combatTypeIndex); + if (points == 0) { + return; } -} -void Player::updateDamageReductionFromItemImbuement( - std::array<double_t, COMBAT_COUNT> &combatReductionArray, std::shared_ptr<Item> item, uint16_t combatTypeIndex -) const { - for (uint8_t imbueSlotId = 0; imbueSlotId < item->getImbuementSlot(); imbueSlotId++) { - ImbuementInfo imbuementInfo; - if (item->getImbuementInfo(imbueSlotId, &imbuementInfo) && imbuementInfo.imbuement) { - int16_t imbuementAbsorption = imbuementInfo.imbuement->absorbPercent[combatTypeIndex]; - if (imbuementAbsorption != 0) { - combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], imbuementAbsorption); + uint16_t stage = 0; + auto chance = static_cast<uint16_t>(normal_random(1, 10000)); + auto critChance = g_configManager().getNumber(HAZARD_CRITICAL_CHANCE); + // Critical chance + if (monster->getHazardSystemCrit() && (lastHazardSystemCriticalHit + g_configManager().getNumber(HAZARD_CRITICAL_INTERVAL)) <= OTSYS_TIME() && chance <= critChance && !damage.critical) { + damage.critical = true; + damage.extension = true; + damage.exString = "(Hazard)"; + + stage = (points - 1) * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_CRITICAL_MULTIPLIER)); + damage.primary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * (5000 + stage)) / 10000)); + damage.secondary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * (5000 + stage)) / 10000)); + lastHazardSystemCriticalHit = OTSYS_TIME(); + } + + // To prevent from punish the player twice with critical + damage boost, just uncomment code from the if + if (monster->getHazardSystemDamageBoost() /* && !damage.critical*/) { + stage = points * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_DAMAGE_MULTIPLIER)); + if (stage != 0) { + damage.extension = true; + damage.exString = "(Hazard)"; + damage.primary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * stage) / 10000)); + if (damage.secondary.value != 0) { + damage.secondary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * stage) / 10000)); } } } } -void Player::updateDamageReductionFromItemAbility( - std::array<double_t, COMBAT_COUNT> &combatReductionArray, std::shared_ptr<Item> item, uint16_t combatTypeIndex -) const { - if (!item) { +void Player::parseAttackDealtHazardSystem(CombatDamage &damage, const std::shared_ptr<Monster> &monster) const { + if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { return; } - const ItemType &itemType = Item::items[item->getID()]; - if (itemType.abilities) { - int16_t elementReduction = itemType.abilities->absorbPercent[combatTypeIndex]; - if (elementReduction != 0) { - combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], elementReduction); - } + if (!monster || !monster->getHazard()) { + return; } -} -double_t Player::calculateDamageReduction(double_t currentTotal, int16_t resistance) const { + if (damage.primary.type == COMBAT_HEALING) { + return; + } + + auto points = getHazardSystemPoints(); + if (m_party) { + for (const auto &partyMember : m_party->getMembers()) { + if (partyMember && partyMember->getHazardSystemPoints() < points) { + points = partyMember->getHazardSystemPoints(); + } + } + + if (m_party->getLeader() && m_party->getLeader()->getHazardSystemPoints() < points) { + points = m_party->getLeader()->getHazardSystemPoints(); + } + } + + if (points == 0) { + return; + } + + // Dodge chance + uint16_t stage; + if (monster->getHazardSystemDodge()) { + stage = points * g_configManager().getNumber(HAZARD_DODGE_MULTIPLIER); + auto chance = static_cast<uint16_t>(normal_random(1, 10000)); + if (chance <= stage) { + damage.primary.value = 0; + damage.secondary.value = 0; + return; + } + } + if (monster->getHazardSystemDefenseBoost()) { + stage = points * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_DEFENSE_MULTIPLIER)); + if (stage != 0) { + damage.exString = fmt::format("(hazard -{}%)", stage / 100.); + damage.primary.value -= static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * stage) / 10000)); + if (damage.secondary.value != 0) { + damage.secondary.value -= static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * stage) / 10000)); + } + } + } +} + +// Points get: +// Points increase: +void Player::setHazardSystemPoints(int32_t count) { + if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { + return; + } + addStorageValue(STORAGEVALUE_HAZARDCOUNT, std::max<int32_t>(0, std::min<int32_t>(0xFFFF, count)), true); + reloadHazardSystemPointsCounter = true; + if (count > 0) { + setIcon("hazard", CreatureIcon(CreatureIconQuests_t::Hazard, count)); + } else { + removeIcon("hazard"); + } +} + +uint16_t Player::getHazardSystemPoints() const { + const int32_t points = getStorageValue(STORAGEVALUE_HAZARDCOUNT); + if (points <= 0) { + return 0; + } + return static_cast<uint16_t>(std::max<int32_t>(0, std::min<int32_t>(0xFFFF, points))); +} + +// Concoction system + +void Player::updateConcoction(uint16_t itemId, uint16_t timeLeft) { + if (timeLeft == 0) { + activeConcoctions.erase(itemId); + } else { + activeConcoctions[itemId] = timeLeft; + } +} + +std::map<uint16_t, uint16_t> Player::getActiveConcoctions() const { + return activeConcoctions; +} + +bool Player::isConcoctionActive(Concoction_t concotion) const { + const auto itemId = static_cast<uint16_t>(concotion); + if (!activeConcoctions.contains(itemId)) { + return false; + } + const auto timeLeft = activeConcoctions.at(itemId); + return timeLeft > 0; +} + +bool Player::checkAutoLoot(bool isBoss) const { + if (!g_configManager().getBoolean(AUTOLOOT)) { + return false; + } + if (g_configManager().getBoolean(VIP_SYSTEM_ENABLED) && g_configManager().getBoolean(VIP_AUTOLOOT_VIP_ONLY) && !isVip()) { + return false; + } + + auto featureKV = kv()->scoped("features")->get("autoloot"); + auto value = featureKV.has_value() ? featureKV->getNumber() : 0; + if (value == 2) { + return true; + } else if (value == 1) { + return !isBoss; + } + return false; +} + +QuickLootFilter_t Player::getQuickLootFilter() const { + return quickLootFilter; +} + +std::vector<std::shared_ptr<Item>> Player::getInventoryItemsFromId(uint16_t itemId, bool ignore /*= true*/) const { + std::vector<std::shared_ptr<Item>> itemVector; + for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { + const auto &item = inventory[i]; + if (!item) { + continue; + } + + if (!ignore && item->getID() == itemId) { + itemVector.emplace_back(item); + } + + if (const auto &container = item->getContainer()) { + for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { + const auto &containerItem = *it; + if (containerItem->getID() == itemId) { + itemVector.emplace_back(containerItem); + } + } + } + } + + return itemVector; +} + +std::array<double_t, COMBAT_COUNT> Player::getFinalDamageReduction() const { + std::array<double_t, COMBAT_COUNT> combatReductionArray {}; + combatReductionArray.fill(0); + calculateDamageReductionFromEquipedItems(combatReductionArray); + for (int combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) { + combatReductionArray[combatTypeIndex] = std::clamp<double_t>( + std::floor(combatReductionArray[combatTypeIndex]), + -100., + 100. + ); + } + return combatReductionArray; +} + +void Player::calculateDamageReductionFromEquipedItems(std::array<double_t, COMBAT_COUNT> &combatReductionArray) const { + for (uint8_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { + const auto &item = inventory[slot]; + if (item) { + calculateDamageReductionFromItem(combatReductionArray, item); + } + } +} + +void Player::calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionArray, const std::shared_ptr<Item> &item) const { + for (uint16_t combatTypeIndex = 0; combatTypeIndex < COMBAT_COUNT; combatTypeIndex++) { + updateDamageReductionFromItemImbuement(combatReductionArray, item, combatTypeIndex); + updateDamageReductionFromItemAbility(combatReductionArray, item, combatTypeIndex); + } +} + +void Player::updateDamageReductionFromItemImbuement( + std::array<double_t, COMBAT_COUNT> &combatReductionArray, const std::shared_ptr<Item> &item, uint16_t combatTypeIndex +) const { + for (uint8_t imbueSlotId = 0; imbueSlotId < item->getImbuementSlot(); imbueSlotId++) { + ImbuementInfo imbuementInfo; + if (item->getImbuementInfo(imbueSlotId, &imbuementInfo) && imbuementInfo.imbuement) { + const int16_t imbuementAbsorption = imbuementInfo.imbuement->absorbPercent[combatTypeIndex]; + if (imbuementAbsorption != 0) { + combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], imbuementAbsorption); + } + } + } +} + +void Player::updateDamageReductionFromItemAbility( + std::array<double_t, COMBAT_COUNT> &combatReductionArray, const std::shared_ptr<Item> &item, uint16_t combatTypeIndex +) const { + if (!item) { + return; + } + + const ItemType &itemType = Item::items[item->getID()]; + if (itemType.abilities) { + const int16_t elementReduction = itemType.abilities->absorbPercent[combatTypeIndex]; + if (elementReduction != 0) { + combatReductionArray[combatTypeIndex] = calculateDamageReduction(combatReductionArray[combatTypeIndex], elementReduction); + } + } +} + +double_t Player::calculateDamageReduction(double_t currentTotal, int16_t resistance) const { return (100 - currentTotal) / 100.0 * resistance + currentTotal; } @@ -3996,7 +5013,7 @@ ItemsTierCountList Player::getStoreInboxItemsId() const { const auto &container = getStoreInbox(); if (container) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; + const auto &item = *it; (itemMap[item->getID()])[item->getTier()] += Item::countByType(item, -1); } } @@ -4008,9 +5025,9 @@ ItemsTierCountList Player::getDepotChestItemsId() const { ItemsTierCountList itemMap; for (const auto &[index, depot] : depotChests) { - const std::shared_ptr<Container> &container = depot->getContainer(); + const auto &container = depot->getContainer(); for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; + const auto &item = *it; (itemMap[item->getID()])[item->getTier()] += Item::countByType(item, -1); } } @@ -4021,11 +5038,15 @@ ItemsTierCountList Player::getDepotChestItemsId() const { ItemsTierCountList Player::getDepotInboxItemsId() const { ItemsTierCountList itemMap; - const std::shared_ptr<Inbox> &inbox = getInbox(); - const std::shared_ptr<Container> &container = inbox->getContainer(); + const auto &inboxPtr = getInbox(); + const auto &container = inboxPtr ? inboxPtr->getContainer() : nullptr; if (container) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { const auto &item = *it; + if (!item) { + continue; + } + (itemMap[item->getID()])[item->getTier()] += Item::countByType(item, -1); } } @@ -4036,22 +5057,22 @@ ItemsTierCountList Player::getDepotInboxItemsId() const { std::vector<std::shared_ptr<Item>> Player::getAllInventoryItems(bool ignoreEquiped /*= false*/, bool ignoreItemWithTier /* false*/) const { std::vector<std::shared_ptr<Item>> itemVector; for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (!item) { continue; } // Only get equiped items if ignored equipped is false if (!ignoreEquiped) { - itemVector.push_back(item); + itemVector.emplace_back(item); } - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const auto &container = item->getContainer()) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { if (ignoreItemWithTier && (*it)->getTier() > 0) { continue; } - itemVector.push_back(*it); + itemVector.emplace_back(*it); } } } @@ -4061,12 +5082,12 @@ std::vector<std::shared_ptr<Item>> Player::getAllInventoryItems(bool ignoreEquip std::vector<std::shared_ptr<Item>> Player::getEquippedAugmentItemsByType(Augment_t augmentType) const { std::vector<std::shared_ptr<Item>> equippedAugmentItemsByType; - const auto equippedAugmentItems = getEquippedItems(); + auto equippedAugmentItems = getEquippedItems(); for (const auto &item : equippedAugmentItems) { - for (auto &augment : item->getAugments()) { + for (const auto &augment : item->getAugments()) { if (augment->type == augmentType) { - equippedAugmentItemsByType.push_back(item); + equippedAugmentItemsByType.emplace_back(item); } } } @@ -4076,20 +5097,20 @@ std::vector<std::shared_ptr<Item>> Player::getEquippedAugmentItemsByType(Augment std::vector<std::shared_ptr<Item>> Player::getEquippedAugmentItems() const { std::vector<std::shared_ptr<Item>> equippedAugmentItems; - const auto equippedItems = getEquippedItems(); + auto equippedItems = getEquippedItems(); for (const auto &item : equippedItems) { - if (item->getAugments().size() < 1) { + if (item->getAugments().empty()) { continue; } - equippedAugmentItems.push_back(item); + equippedAugmentItems.emplace_back(item); } return equippedAugmentItems; } std::vector<std::shared_ptr<Item>> Player::getEquippedItems() const { - std::vector<Slots_t> valid_slots { + static const std::vector valid_slots { CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_BACKPACK, @@ -4103,12 +5124,12 @@ std::vector<std::shared_ptr<Item>> Player::getEquippedItems() const { std::vector<std::shared_ptr<Item>> valid_items; for (const auto &slot : valid_slots) { - std::shared_ptr<Item> item = inventory[slot]; + const auto &item = inventory[slot]; if (!item) { continue; } - valid_items.push_back(item); + valid_items.emplace_back(item); } return valid_items; @@ -4143,7 +5164,7 @@ std::map<uint16_t, uint16_t> &Player::getAllSaleItemIdAndCount(std::map<uint16_t void Player::getAllItemTypeCountAndSubtype(std::map<uint32_t, uint32_t> &countMap) const { for (const auto &item : getAllInventoryItems()) { - uint16_t itemId = item->getID(); + const uint16_t itemId = item->getID(); if (Item::items[itemId].isFluidContainer()) { countMap[static_cast<uint32_t>(itemId) | (item->getAttribute<uint32_t>(ItemAttribute_t::FLUIDTYPE)) << 16] += item->getItemCount(); } else { @@ -4152,8 +5173,8 @@ void Player::getAllItemTypeCountAndSubtype(std::map<uint32_t, uint32_t> &countMa } } -std::shared_ptr<Item> Player::getForgeItemFromId(uint16_t itemId, uint8_t tier) { - for (auto item : getAllInventoryItems(true)) { +std::shared_ptr<Item> Player::getForgeItemFromId(uint16_t itemId, uint8_t tier) const { + for (const auto &item : getAllInventoryItems(true)) { if (item->hasImbuements()) { continue; } @@ -4173,174 +5194,80 @@ std::shared_ptr<Thing> Player::getThing(size_t index) const { return nullptr; } -void Player::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link /*= LINK_OWNER*/) { - if (link == LINK_OWNER) { - // calling movement scripts - g_moveEvents().onPlayerEquip(getPlayer(), thing->getItem(), static_cast<Slots_t>(index), false); +// TODO: review this function +bool Player::updateSaleShopList(const std::shared_ptr<Item> &item) { + const uint16_t itemId = item->getID(); + if (!itemId || !item) { + return true; } - bool requireListUpdate = true; - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - std::shared_ptr<Item> i = (oldParent ? oldParent->getItem() : nullptr); - const auto &container = i ? i->getContainer() : nullptr; - if (container) { - requireListUpdate = container->getHoldingPlayer() != getPlayer(); - } else { - requireListUpdate = oldParent != getPlayer(); - } + g_dispatcher().addEvent([creatureId = getID()] { g_game().updatePlayerSaleItems(creatureId); }, __FUNCTION__); + scheduledSaleUpdate = true; + return true; +} - updateInventoryWeight(); - updateItemsLight(); - sendInventoryIds(); - sendStats(); +bool Player::hasShopItemForSale(uint16_t itemId, uint8_t subType) const { + if (!shopOwner) { + return false; } - if (std::shared_ptr<Item> item = thing->getItem()) { - if (std::shared_ptr<Container> container = item->getContainer()) { - onSendContainer(container); - } + const ItemType &itemType = Item::items[itemId]; + const auto &shoplist = shopOwner->getShopItemVector(getGUID()); + return std::ranges::any_of(shoplist, [&](const ShopBlock &shopBlock) { + return shopBlock.itemId == itemId && shopBlock.itemBuyPrice != 0 && (!itemType.isFluidContainer() || shopBlock.itemSubType == subType); + }); +} - if (shopOwner && !scheduledSaleUpdate && requireListUpdate) { - updateSaleShopList(item); - } - } else if (std::shared_ptr<Creature> creature = thing->getCreature()) { - if (creature == getPlayer()) { - // check containers - std::vector<std::shared_ptr<Container>> containers; +void Player::internalAddThing(const std::shared_ptr<Thing> &thing) { + internalAddThing(0, thing); +} - for (const auto &it : openContainers) { - std::shared_ptr<Container> container = it.second.container; - if (container == nullptr) { - continue; - } +void Player::internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) { + if (!thing) { + return; + } - if (!Position::areInRange<1, 1, 0>(container->getPosition(), getPosition())) { - containers.push_back(container); - } - } + const auto &item = thing->getItem(); + if (!item) { + return; + } - for (const std::shared_ptr<Container> &container : containers) { - autoCloseContainers(container); - } + // index == 0 means we should equip this item at the most appropiate slot (no action required here) + if (index >= CONST_SLOT_FIRST && index <= CONST_SLOT_LAST) { + if (inventory[index]) { + return; } + + inventory[index] = item; + item->setParent(static_self_cast<Player>()); } } -void Player::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link /*= LINK_OWNER*/) { - if (link == LINK_OWNER) { - // calling movement scripts - g_moveEvents().onPlayerDeEquip(getPlayer(), thing->getItem(), static_cast<Slots_t>(index)); - } +// safe-trade functions - bool requireListUpdate = true; +void Player::setTradeState(TradeState_t state) { + tradeState = state; +} - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - std::shared_ptr<Item> i = (newParent ? newParent->getItem() : nullptr); - const auto &container = i ? i->getContainer() : nullptr; - if (container) { - requireListUpdate = container->getHoldingPlayer() != getPlayer(); - } else { - requireListUpdate = newParent != getPlayer(); - } +TradeState_t Player::getTradeState() const { + return tradeState; +} - updateInventoryWeight(); - updateItemsLight(); - sendInventoryIds(); - sendStats(); - } +std::shared_ptr<Item> Player::getTradeItem() { + return tradeItem; +} - if (std::shared_ptr<Item> item = thing->getItem()) { - if (std::shared_ptr<Container> container = item->getContainer()) { - checkLootContainers(container); +// shop functions - if (container->isRemoved() || !Position::areInRange<1, 1, 0>(getPosition(), container->getPosition())) { - autoCloseContainers(container); - } else if (container->getTopParent() == getPlayer()) { - onSendContainer(container); - } else if (std::shared_ptr<Container> topContainer = std::dynamic_pointer_cast<Container>(container->getTopParent())) { - if (std::shared_ptr<DepotChest> depotChest = std::dynamic_pointer_cast<DepotChest>(topContainer)) { - bool isOwner = false; +void Player::setShopOwner(std::shared_ptr<Npc> owner) { + shopOwner = std::move(owner); +} - for (const auto &it : depotChests) { - if (it.second == depotChest) { - isOwner = true; - it.second->stopDecaying(); - onSendContainer(container); - } - } +std::shared_ptr<Npc> Player::getShopOwner() const { + return shopOwner; +} - if (!isOwner) { - autoCloseContainers(container); - } - } else { - onSendContainer(container); - } - } else { - autoCloseContainers(container); - } - } - - // force list update if item exists tier - if (item->getTier() > 0 && !requireListUpdate) { - requireListUpdate = true; - } - - if (shopOwner && !scheduledSaleUpdate && requireListUpdate) { - updateSaleShopList(item); - } - } -} - -// i will keep this function so it can be reviewed -bool Player::updateSaleShopList(std::shared_ptr<Item> item) { - uint16_t itemId = item->getID(); - if (!itemId || !item) { - return true; - } - - g_dispatcher().addEvent([creatureId = getID()] { g_game().updatePlayerSaleItems(creatureId); }, __FUNCTION__); - scheduledSaleUpdate = true; - return true; -} - -bool Player::hasShopItemForSale(uint16_t itemId, uint8_t subType) const { - if (!shopOwner) { - return false; - } - - const ItemType &itemType = Item::items[itemId]; - const auto &shoplist = shopOwner->getShopItemVector(getGUID()); - return std::any_of(shoplist.begin(), shoplist.end(), [&](const ShopBlock &shopBlock) { - return shopBlock.itemId == itemId && shopBlock.itemBuyPrice != 0 && (!itemType.isFluidContainer() || shopBlock.itemSubType == subType); - }); -} - -void Player::internalAddThing(std::shared_ptr<Thing> thing) { - internalAddThing(0, thing); -} - -void Player::internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) { - if (!thing) { - return; - } - - std::shared_ptr<Item> item = thing->getItem(); - if (!item) { - return; - } - - // index == 0 means we should equip this item at the most appropiate slot (no action required here) - if (index >= CONST_SLOT_FIRST && index <= CONST_SLOT_LAST) { - if (inventory[index]) { - return; - } - - inventory[index] = item; - item->setParent(static_self_cast<Player>()); - } -} - -bool Player::setFollowCreature(std::shared_ptr<Creature> creature) { +bool Player::setFollowCreature(const std::shared_ptr<Creature> &creature) { if (!Creature::setFollowCreature(creature)) { setFollowCreature(nullptr); setAttackedCreature(nullptr); @@ -4353,13 +5280,13 @@ bool Player::setFollowCreature(std::shared_ptr<Creature> creature) { return true; } -bool Player::setAttackedCreature(std::shared_ptr<Creature> creature) { +bool Player::setAttackedCreature(const std::shared_ptr<Creature> &creature) { if (!Creature::setAttackedCreature(creature)) { sendCancelTarget(); return false; } - auto followCreature = getFollowCreature(); + const auto &followCreature = getFollowCreature(); if (chaseMode && creature) { if (followCreature != creature) { setFollowCreature(creature); @@ -4393,64 +5320,9 @@ void Player::getPathSearchParams(const std::shared_ptr<Creature> &creature, Find fpp.fullPathSearch = true; } -void Player::doAttacking(uint32_t) { - if (lastAttack == 0) { - lastAttack = OTSYS_TIME() - getAttackSpeed() - 1; - } - - if (hasCondition(CONDITION_PACIFIED)) { - return; - } - - auto attackedCreature = getAttackedCreature(); - if (!attackedCreature) { - return; - } - - if ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()) { - bool result = false; - - std::shared_ptr<Item> tool = getWeapon(); - const WeaponShared_ptr weapon = g_weapons().getWeapon(tool); - uint32_t delay = getAttackSpeed(); - bool classicSpeed = g_configManager().getBoolean(CLASSIC_ATTACK_SPEED); - - if (weapon) { - if (!weapon->interruptSwing()) { - result = weapon->useWeapon(static_self_cast<Player>(), tool, attackedCreature); - } else if (!classicSpeed && !canDoAction()) { - delay = getNextActionTime(); - } else { - result = weapon->useWeapon(static_self_cast<Player>(), tool, attackedCreature); - } - } else if (hasWeaponDistanceEquipped()) { - return; - } else { - result = Weapon::useFist(static_self_cast<Player>(), attackedCreature); - } - - const auto &task = createPlayerTask( - std::max<uint32_t>(SCHEDULER_MINTICKS, delay), - [playerId = getID()] { g_game().checkCreatureAttack(playerId); }, - __FUNCTION__ - ); - - if (!classicSpeed) { - setNextActionTask(task, false); - } else { - g_dispatcher().scheduleEvent(task); - } - - if (result) { - updateLastAggressiveAction(); - updateLastAttack(); - } - } -} - -uint64_t Player::getGainedExperience(std::shared_ptr<Creature> attacker) const { +uint64_t Player::getGainedExperience(const std::shared_ptr<Creature> &attacker) const { if (g_configManager().getBoolean(EXPERIENCE_FROM_PLAYERS)) { - auto attackerPlayer = attacker->getPlayer(); + const auto &attackerPlayer = attacker->getPlayer(); if (attackerPlayer && attackerPlayer.get() != this && skillLoss && std::abs(static_cast<int32_t>(attackerPlayer->getLevel() - level)) <= g_configManager().getNumber(EXP_FROM_PLAYERS_LEVEL_RANGE)) { return std::max<uint64_t>(0, std::floor(getLostExperience() * getDamageRatio(attacker) * 0.75)); } @@ -4465,10 +5337,10 @@ void Player::onFollowCreature(const std::shared_ptr<Creature> &creature) { } void Player::setChaseMode(bool mode) { - bool prevChaseMode = chaseMode; + const bool prevChaseMode = chaseMode; chaseMode = mode; - auto attackedCreature = getAttackedCreature(); - auto followCreature = getFollowCreature(); + const auto &attackedCreature = getAttackedCreature(); + const auto &followCreature = getFollowCreature(); if (prevChaseMode != chaseMode) { if (chaseMode) { @@ -4483,6 +5355,22 @@ void Player::setChaseMode(bool mode) { } } +void Player::setFightMode(FightMode_t mode) { + fightMode = mode; +} + +void Player::setSecureMode(bool mode) { + secureMode = mode; +} + +Faction_t Player::getFaction() const { + return faction; +} + +void Player::setFaction(Faction_t factionId) { + faction = factionId; +} + void Player::onWalkAborted() { setNextWalkActionTask(nullptr); sendCancelWalk(); @@ -4497,8 +5385,10 @@ void Player::onWalkComplete() { */ g_logger().debug("[Player::onWalkComplete] Executing feared conditions as players completed it's walk."); - std::shared_ptr<Condition> f = getCondition(CONDITION_FEARED); - f->executeCondition(static_self_cast<Player>(), 0); + const auto &fearedCondition = getCondition(CONDITION_FEARED); + if (fearedCondition) { + fearedCondition->executeCondition(static_self_cast<Player>(), 0); + } } if (walkTask) { @@ -4522,9 +5412,9 @@ void Player::updateItemsLight(bool internal /*=false*/) { LightInfo maxLight; for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; + const auto &item = inventory[i]; if (item) { - LightInfo curLight = item->getLightInfo(); + const auto &curLight = item->getLightInfo(); if (curLight.level > maxLight.level) { maxLight = curLight; @@ -4630,12 +5520,16 @@ void Player::onEndCondition(ConditionType_t type) { sendIcons(); } -void Player::onCombatRemoveCondition(std::shared_ptr<Condition> condition) { +void Player::onCombatRemoveCondition(const std::shared_ptr<Condition> &condition) { + if (!condition) { + return; + } + // Creature::onCombatRemoveCondition(condition); if (condition->getId() > 0) { // Means the condition is from an item, id == slot if (g_game().getWorldType() == WORLD_TYPE_PVP_ENFORCED) { - std::shared_ptr<Item> item = getInventoryItem(static_cast<Slots_t>(condition->getId())); + const auto &item = getInventoryItem(static_cast<Slots_t>(condition->getId())); if (item) { // 25% chance to destroy the item if (25 >= uniform_random(1, 100)) { @@ -4658,9 +5552,13 @@ void Player::onCombatRemoveCondition(std::shared_ptr<Condition> condition) { } } -void Player::onAttackedCreature(std::shared_ptr<Creature> target) { +void Player::onAttackedCreature(const std::shared_ptr<Creature> &target) { Creature::onAttackedCreature(target); + if (!target) { + return; + } + if (target->getZoneType() == ZONE_PVP) { return; } @@ -4674,7 +5572,7 @@ void Player::onAttackedCreature(std::shared_ptr<Creature> target) { return; } - auto targetPlayer = target->getPlayer(); + const auto &targetPlayer = target->getPlayer(); if (targetPlayer && !isPartner(targetPlayer) && !isGuildMate(targetPlayer)) { if (!pzLocked && g_game().getWorldType() == WORLD_TYPE_PVP_ENFORCED) { pzLocked = true; @@ -4732,12 +5630,12 @@ void Player::onPlacedCreature() { sendUnjustifiedPoints(); } -void Player::onAttackedCreatureDrainHealth(std::shared_ptr<Creature> target, int32_t points) { +void Player::onAttackedCreatureDrainHealth(const std::shared_ptr<Creature> &target, int32_t points) { Creature::onAttackedCreatureDrainHealth(target, points); if (target) { if (m_party && !Combat::isPlayerCombat(target)) { - auto tmpMonster = target->getMonster(); + const auto &tmpMonster = target->getMonster(); if (tmpMonster && tmpMonster->isHostile()) { // We have fulfilled a requirement for shared experience m_party->updatePlayerTicks(static_self_cast<Player>(), points); @@ -4746,14 +5644,14 @@ void Player::onAttackedCreatureDrainHealth(std::shared_ptr<Creature> target, int } } -void Player::onTargetCreatureGainHealth(std::shared_ptr<Creature> target, int32_t points) { +void Player::onTargetCreatureGainHealth(const std::shared_ptr<Creature> &target, int32_t points) { if (target && m_party) { std::shared_ptr<Player> tmpPlayer = nullptr; if (isPartner(tmpPlayer) && (tmpPlayer != getPlayer())) { tmpPlayer = target->getPlayer(); - } else if (std::shared_ptr<Creature> targetMaster = target->getMaster()) { - if (std::shared_ptr<Player> targetMasterPlayer = targetMaster->getPlayer()) { + } else if (const auto &targetMaster = target->getMaster()) { + if (const auto &targetMasterPlayer = targetMaster->getPlayer()) { tmpPlayer = targetMasterPlayer; } } @@ -4786,7 +5684,7 @@ bool Player::onKilledPlayer(const std::shared_ptr<Player> &target, bool lastHit) if (lastHit && hasCondition(CONDITION_INFIGHT)) { pzLocked = true; - std::shared_ptr<Condition> condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(WHITE_SKULL_TIME), 0); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_configManager().getNumber(WHITE_SKULL_TIME), 0); addCondition(condition); } } @@ -4804,7 +5702,7 @@ void Player::addHuntingTaskKill(const std::shared_ptr<MonsterType> &mType) { taskSlot->currentKills += 1; if ((taskSlot->upgrade && taskSlot->currentKills >= option->secondKills) || (!taskSlot->upgrade && taskSlot->currentKills >= option->firstKills)) { taskSlot->state = PreyTaskDataState_Completed; - std::string message = "You succesfully finished your hunting task. Your reward is ready to be claimed!"; + const std::string message = "You succesfully finished your hunting task. Your reward is ready to be claimed!"; sendTextMessage(MESSAGE_STATUS, message); } reloadTaskSlot(taskSlot->id); @@ -4840,14 +5738,18 @@ bool Player::onKilledMonster(const std::shared_ptr<Monster> &monster) { if (monster->hasBeenSummoned()) { return false; } - auto mType = monster->getMonsterType(); + const auto &mType = monster->getMonsterType(); + if (mType == nullptr) { + g_logger().error("[{}] Monster type is null.", __FUNCTION__); + return false; + } addHuntingTaskKill(mType); addBestiaryKill(mType); addBosstiaryKill(mType); return false; } -void Player::gainExperience(uint64_t gainExp, std::shared_ptr<Creature> target) { +void Player::gainExperience(uint64_t gainExp, const std::shared_ptr<Creature> &target) { if (hasFlag(PlayerFlags_t::NotGainExperience) || gainExp == 0 || staminaMinutes == 0) { return; } @@ -4855,7 +5757,7 @@ void Player::gainExperience(uint64_t gainExp, std::shared_ptr<Creature> target) addExperience(target, gainExp, true); } -void Player::onGainExperience(uint64_t gainExp, std::shared_ptr<Creature> target) { +void Player::onGainExperience(uint64_t gainExp, const std::shared_ptr<Creature> &target) { if (hasFlag(PlayerFlags_t::NotGainExperience)) { return; } @@ -4870,7 +5772,7 @@ void Player::onGainExperience(uint64_t gainExp, std::shared_ptr<Creature> target gainExperience(gainExp, target); } -void Player::onGainSharedExperience(uint64_t gainExp, std::shared_ptr<Creature> target) { +void Player::onGainSharedExperience(uint64_t gainExp, const std::shared_ptr<Creature> &target) { gainExperience(gainExp, target); } @@ -4893,7 +5795,7 @@ bool Player::isAttackable() const { return !hasFlag(PlayerFlags_t::CannotBeAttacked); } -bool Player::lastHitIsPlayer(std::shared_ptr<Creature> lastHitCreature) { +bool Player::lastHitIsPlayer(const std::shared_ptr<Creature> &lastHitCreature) { if (!lastHitCreature) { return false; } @@ -4902,7 +5804,7 @@ bool Player::lastHitIsPlayer(std::shared_ptr<Creature> lastHitCreature) { return true; } - std::shared_ptr<Creature> lastHitMaster = lastHitCreature->getMaster(); + const auto &lastHitMaster = lastHitCreature->getMaster(); return lastHitMaster && lastHitMaster->getPlayer(); } @@ -4952,7 +5854,7 @@ bool Player::canWear(uint16_t lookType, uint8_t addons) const { return true; } - for (const OutfitEntry &outfitEntry : outfits) { + for (const auto &outfitEntry : outfits) { if (outfitEntry.lookType != lookType) { continue; } @@ -4961,42 +5863,39 @@ bool Player::canWear(uint16_t lookType, uint8_t addons) const { return false; } -bool Player::canLogout() { - if (isConnecting) { - return false; - } - - auto tile = getTile(); - if (!tile) { - return false; - } - - if (tile->hasFlag(TILESTATE_NOLOGOUT)) { - return false; - } - - if (tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - return true; - } - - return !isPzLocked() && !hasCondition(CONDITION_INFIGHT); -} - void Player::genReservedStorageRange() { // generate outfits range uint32_t outfits_key = PSTRG_OUTFITS_RANGE_START; - for (const OutfitEntry &entry : outfits) { + for (const auto &entry : outfits) { storageMap[++outfits_key] = (entry.lookType << 16) | entry.addons; } // generate familiars range uint32_t familiar_key = PSTRG_FAMILIARS_RANGE_START; - for (const FamiliarEntry &entry : familiars) { + for (const auto &entry : familiars) { storageMap[++familiar_key] = (entry.lookType << 16); } } +void Player::setSpecialMenuAvailable(bool supplyStashBool, bool marketMenuBool, bool depotSearchBool) { + // Closing depot search when player have special container disabled and it's still open. + if (isDepotSearchOpen() && !depotSearchBool && depotSearch) { + depotSearchOnItem = { 0, 0 }; + sendCloseDepotSearch(); + } + + // Menu option 'stow, stow container ...' + // Menu option 'show in market' + // Menu option to open depot search + supplyStash = supplyStashBool; + marketMenu = marketMenuBool; + depotSearch = depotSearchBool; + if (client) { + client->sendSpecialContainersAvailable(); + } +} + void Player::addOutfit(uint16_t lookType, uint8_t addons) { - for (OutfitEntry &outfitEntry : outfits) { + for (auto &outfitEntry : outfits) { if (outfitEntry.lookType == lookType) { outfitEntry.addons |= addons; return; @@ -5007,7 +5906,7 @@ void Player::addOutfit(uint16_t lookType, uint8_t addons) { bool Player::removeOutfit(uint16_t lookType) { for (auto it = outfits.begin(), end = outfits.end(); it != end; ++it) { - OutfitEntry &entry = *it; + const auto &entry = *it; if (entry.lookType == lookType) { outfits.erase(it); return true; @@ -5071,32 +5970,29 @@ bool Player::canFamiliar(uint16_t lookType) const { return true; } - for (const FamiliarEntry &familiarEntry : familiars) { - if (familiarEntry.lookType == lookType) { - return true; - } + if (std::ranges::any_of(familiars, [&](const FamiliarEntry &familiarEntry) { + return familiarEntry.lookType == lookType; + })) { + return true; } + return false; } void Player::addFamiliar(uint16_t lookType) { - for (FamiliarEntry &familiarEntry : familiars) { - if (familiarEntry.lookType == lookType) { - return; - } + if (std::ranges::none_of(familiars, [&](const FamiliarEntry &familiarEntry) { + return familiarEntry.lookType == lookType; + })) { + familiars.emplace_back(lookType); } - familiars.emplace_back(lookType); } bool Player::removeFamiliar(uint16_t lookType) { - for (auto it = familiars.begin(), end = familiars.end(); it != end; ++it) { - FamiliarEntry &entry = *it; - if (entry.lookType == lookType) { - familiars.erase(it); - return true; - } - } - return false; + const auto initialSize = familiars.size(); + std::erase_if(familiars, [lookType](const FamiliarEntry &entry) { + return entry.lookType == lookType; + }); + return familiars.size() != initialSize; } bool Player::getFamiliar(const std::shared_ptr<Familiar> &familiar) const { @@ -5108,11 +6004,9 @@ bool Player::getFamiliar(const std::shared_ptr<Familiar> &familiar) const { return false; } - for (const FamiliarEntry &familiarEntry : familiars) { - if (familiarEntry.lookType != familiar->lookType) { - continue; - } - + if (std::ranges::any_of(familiars, [&](const FamiliarEntry &familiarEntry) { + return familiarEntry.lookType == familiar->lookType; + })) { return true; } @@ -5123,6 +6017,102 @@ bool Player::getFamiliar(const std::shared_ptr<Familiar> &familiar) const { return true; } +void Player::setFamiliarLooktype(uint16_t familiarLooktype) { + this->defaultOutfit.lookFamiliarsType = familiarLooktype; +} + +bool Player::canLogout() { + if (isConnecting) { + return false; + } + + const auto &tile = getTile(); + if (!tile) { + return false; + } + + if (tile->hasFlag(TILESTATE_NOLOGOUT)) { + return false; + } + + if (tile->hasFlag(TILESTATE_PROTECTIONZONE)) { + return true; + } + + return !isPzLocked() && !hasCondition(CONDITION_INFIGHT); +} + +bool Player::hasKilled(const std::shared_ptr<Player> &player) const { + return std::ranges::any_of(unjustifiedKills, [&](const auto &kill) { + return kill.target == player->getGUID() && (getTimeNow() - kill.time) < g_configManager().getNumber(ORANGE_SKULL_DURATION) * 24 * 60 * 60 && kill.unavenged; + }); +} + +size_t Player::getMaxDepotItems() const { + if (group->maxDepotItems != 0) { + return group->maxDepotItems; + } + if (isPremium()) { + return g_configManager().getNumber(PREMIUM_DEPOT_LIMIT); + } + return g_configManager().getNumber(FREE_DEPOT_LIMIT); +} + +// tile +// send methods +// tile +// send methods + +void Player::sendAddTileItem(const std::shared_ptr<Tile> &itemTile, const Position &pos, const std::shared_ptr<Item> &item) { + if (client) { + int32_t stackpos = itemTile->getStackposOfItem(static_self_cast<Player>(), item); + if (stackpos != -1) { + client->sendAddTileItem(pos, stackpos, item); + } + } +} + +void Player::sendUpdateTileItem(const std::shared_ptr<Tile> &updateTile, const Position &pos, const std::shared_ptr<Item> &item) { + if (client) { + int32_t stackpos = updateTile->getStackposOfItem(static_self_cast<Player>(), item); + if (stackpos != -1) { + client->sendUpdateTileItem(pos, stackpos, item); + } + } +} + +void Player::sendRemoveTileThing(const Position &pos, int32_t stackpos) const { + if (stackpos != -1 && client) { + client->sendRemoveTileThing(pos, stackpos); + } +} + +void Player::sendUpdateTileCreature(const std::shared_ptr<Creature> &creature) { + if (client) { + client->sendUpdateTileCreature(creature->getPosition(), creature->getTile()->getClientIndexOfCreature(static_self_cast<Player>(), creature), creature); + } +} + +std::string Player::getObjectPronoun() const { + return getPlayerObjectPronoun(pronoun, sex, name); +} + +std::string Player::getSubjectPronoun() const { + return getPlayerSubjectPronoun(pronoun, sex, name); +} + +std::string Player::getPossessivePronoun() const { + return getPlayerPossessivePronoun(pronoun, sex, name); +} + +std::string Player::getReflexivePronoun() const { + return getPlayerReflexivePronoun(pronoun, sex, name); +} + +std::string Player::getSubjectVerb(bool past) const { + return getVerbForPronoun(pronoun, past); +} + void Player::setSex(PlayerSex_t newSex) { sex = newSex; } @@ -5138,18 +6128,18 @@ Skulls_t Player::getSkull() const { return skull; } -Skulls_t Player::getSkullClient(std::shared_ptr<Creature> creature) { +Skulls_t Player::getSkullClient(const std::shared_ptr<Creature> &creature) { if (!creature || g_game().getWorldType() != WORLD_TYPE_PVP) { return SKULL_NONE; } - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player && player->getSkull() == SKULL_NONE) { if (player.get() == this) { - for (const auto &kill : unjustifiedKills) { - if (kill.unavenged && (time(nullptr) - kill.time) < g_configManager().getNumber(ORANGE_SKULL_DURATION) * 24 * 60 * 60) { - return SKULL_ORANGE; - } + if (std::ranges::any_of(unjustifiedKills, [&](const auto &kill) { + return kill.unavenged && (getTimeNow() - kill.time) < g_configManager().getNumber(ORANGE_SKULL_DURATION) * 24 * 60 * 60; + })) { + return SKULL_ORANGE; } } @@ -5168,17 +6158,15 @@ Skulls_t Player::getSkullClient(std::shared_ptr<Creature> creature) { return Creature::getSkullClient(creature); } -bool Player::hasKilled(std::shared_ptr<Player> player) const { - for (const auto &kill : unjustifiedKills) { - if (kill.target == player->getGUID() && (time(nullptr) - kill.time) < g_configManager().getNumber(ORANGE_SKULL_DURATION) * 24 * 60 * 60 && kill.unavenged) { - return true; - } - } +int64_t Player::getSkullTicks() const { + return skullTicks; +} - return false; +void Player::setSkullTicks(int64_t ticks) { + skullTicks = ticks; } -bool Player::hasAttacked(std::shared_ptr<Player> attacked) const { +bool Player::hasAttacked(const std::shared_ptr<Player> &attacked) const { if (hasFlag(PlayerFlags_t::NotGainInFight) || !attacked) { return false; } @@ -5186,7 +6174,7 @@ bool Player::hasAttacked(std::shared_ptr<Player> attacked) const { return attackedSet.contains(attacked->guid); } -void Player::addAttacked(std::shared_ptr<Player> attacked) { +void Player::addAttacked(const std::shared_ptr<Player> &attacked) { if (hasFlag(PlayerFlags_t::NotGainInFight) || !attacked || attacked == getPlayer()) { return; } @@ -5194,7 +6182,7 @@ void Player::addAttacked(std::shared_ptr<Player> attacked) { attackedSet.emplace(attacked->guid); } -void Player::removeAttacked(std::shared_ptr<Player> attacked) { +void Player::removeAttacked(const std::shared_ptr<Player> &attacked) { if (!attacked || attacked == getPlayer()) { return; } @@ -5206,7 +6194,7 @@ void Player::clearAttacked() { attackedSet.clear(); } -void Player::addUnjustifiedDead(std::shared_ptr<Player> attacked) { +void Player::addUnjustifiedDead(const std::shared_ptr<Player> &attacked) { if (hasFlag(PlayerFlags_t::NotGainInFight) || attacked == getPlayer() || g_game().getWorldType() == WORLD_TYPE_PVP_ENFORCED) { return; } @@ -5247,8 +6235,20 @@ void Player::addUnjustifiedDead(std::shared_ptr<Player> attacked) { sendUnjustifiedPoints(); } +void Player::sendCreatureEmblem(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendCreatureEmblem(creature); + } +} + +void Player::sendCreatureSkull(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendCreatureSkull(creature); + } +} + void Player::checkSkullTicks(int64_t ticks) { - int64_t newTicks = skullTicks - ticks; + const int64_t newTicks = skullTicks - ticks; if (newTicks < 0) { skullTicks = 0; } else { @@ -5260,14 +6260,44 @@ void Player::checkSkullTicks(int64_t ticks) { } } -bool Player::isPromoted() const { - uint16_t promotedVocation = g_vocations().getPromotedVocation(vocation->getId()); - return promotedVocation == VOCATION_NONE && vocation->getId() != promotedVocation; -} +void Player::updateBaseSpeed() { + if (baseSpeed >= PLAYER_MAX_SPEED) { + return; + } + + if (!hasFlag(PlayerFlags_t::SetMaxSpeed)) { + baseSpeed = static_cast<uint16_t>(vocation->getBaseSpeed() + (level - 1)); + } else { + baseSpeed = PLAYER_MAX_SPEED; + } +} + +bool Player::isPromoted() const { + const uint16_t promotedVocation = g_vocations().getPromotedVocation(vocation->getId()); + return promotedVocation == VOCATION_NONE && vocation->getId() != promotedVocation; +} + +uint32_t Player::getAttackSpeed() const { + bool onFistAttackSpeed = g_configManager().getBoolean(TOGGLE_ATTACK_SPEED_ONFIST); + uint32_t MAX_ATTACK_SPEED = g_configManager().getNumber(MAX_SPEED_ATTACKONFIST); + if (onFistAttackSpeed) { + uint32_t baseAttackSpeed = vocation->getAttackSpeed(); + uint32_t skillLevel = getSkillLevel(SKILL_FIST); + uint32_t attackSpeed = baseAttackSpeed - (skillLevel * g_configManager().getNumber(MULTIPLIER_ATTACKONFIST)); + + if (attackSpeed < MAX_ATTACK_SPEED) { + attackSpeed = MAX_ATTACK_SPEED; + } + + return attackSpeed; + } else { + return vocation->getAttackSpeed(); + } +} double Player::getLostPercent() const { int32_t blessingCount = 0; - uint8_t maxBlessing = (operatingSystem == CLIENTOS_NEW_WINDOWS || operatingSystem == CLIENTOS_NEW_MAC) ? 8 : 6; + const uint8_t maxBlessing = (operatingSystem == CLIENTOS_NEW_WINDOWS || operatingSystem == CLIENTOS_NEW_MAC) ? 8 : 6; for (int i = 2; i <= maxBlessing; i++) { if (hasBlessing(i)) { blessingCount++; @@ -5284,51 +6314,41 @@ double Player::getLostPercent() const { return std::max<int32_t>(0, deathLosePercent) / 100.; } + bool isRetro = g_configManager().getBoolean(TOGGLE_SERVER_IS_RETRO); + const auto factor = (isRetro ? 6.31 : 8); + double percentReduction = (blessingCount * factor) / 100.; + double lossPercent; if (level >= 24) { - double tmpLevel = level + (levelPercent / 100.); + const double tmpLevel = level + (levelPercent / 100.); lossPercent = ((tmpLevel + 50) * 50 * ((tmpLevel * tmpLevel) - (5 * tmpLevel) + 8)) / experience; } else { - lossPercent = 5; + percentReduction = (percentReduction >= 0.40 ? 0.50 : percentReduction); + lossPercent = 10; } - double percentReduction = 0; + g_logger().debug("[{}] - lossPercent {}", __FUNCTION__, lossPercent); + g_logger().debug("[{}] - before promotion {}", __FUNCTION__, percentReduction); + if (isPromoted()) { - percentReduction += 30; + percentReduction += 30 / 100.; + g_logger().debug("[{}] - after promotion {}", __FUNCTION__, percentReduction); } - percentReduction += blessingCount * 8; - return lossPercent * (1 - (percentReduction / 100.)) / 100.; -} + g_logger().debug("[{}] - total lost percent {}", __FUNCTION__, (lossPercent * (1 - percentReduction)) / 100.); -void Player::learnInstantSpell(const std::string &spellName) { - if (!hasLearnedInstantSpell(spellName)) { - learnedInstantSpellList.emplace_back(spellName); - } + return (lossPercent * (1 - percentReduction)) / 100.; } -void Player::forgetInstantSpell(const std::string &spellName) { - std::erase(learnedInstantSpellList, spellName); +[[nodiscard]] const std::string &Player::getGuildNick() const { + return guildNick; } -bool Player::hasLearnedInstantSpell(const std::string &spellName) const { - if (hasFlag(PlayerFlags_t::CannotUseSpells)) { - return false; - } - - if (hasFlag(PlayerFlags_t::IgnoreSpellCheck)) { - return true; - } - - for (const auto &learnedSpellName : learnedInstantSpellList) { - if (strcasecmp(learnedSpellName.c_str(), spellName.c_str()) == 0) { - return true; - } - } - return false; +void Player::setGuildNick(std::string nick) { + guildNick = std::move(nick); } -bool Player::isInWar(std::shared_ptr<Player> player) const { +bool Player::isInWar(const std::shared_ptr<Player> &player) const { if (!player || !guild) { return false; } @@ -5342,14 +6362,14 @@ bool Player::isInWar(std::shared_ptr<Player> player) const { } bool Player::isInWarList(uint32_t guildId) const { - return std::find(guildWarVector.begin(), guildWarVector.end(), guildId) != guildWarVector.end(); + return std::ranges::find(guildWarVector, guildId) != guildWarVector.end(); } uint32_t Player::getMagicLevel() const { uint32_t magic = std::max<int32_t>(0, getLoyaltyMagicLevel() + varStats[STAT_MAGICPOINTS]); // Wheel of destiny magic bonus magic += m_wheelPlayer->getStat(WheelStat_t::MAGIC); // Regular bonus - magic += m_wheelPlayer->getMajorStatConditional("Positional Tatics", WheelMajor_t::MAGIC); // Revelation bonus + magic += m_wheelPlayer->getMajorStatConditional("Positional Tactics", WheelMajor_t::MAGIC); // Revelation bonus return magic; } @@ -5363,7 +6383,7 @@ uint32_t Player::getLoyaltyMagicLevel() const { } absl::uint128 spent = manaSpent; - absl::uint128 totalMana = vocation->getTotalMana(level) + spent; + const absl::uint128 totalMana = vocation->getTotalMana(level) + spent; absl::uint128 loyaltyMana = (totalMana * getLoyaltyBonus()) / 100; while ((spent + loyaltyMana) >= nextReqMana) { loyaltyMana -= nextReqMana - spent; @@ -5380,15 +6400,6 @@ uint32_t Player::getLoyaltyMagicLevel() const { return level; } -uint32_t Player::getCapacity() const { - if (hasFlag(PlayerFlags_t::CannotPickupItem)) { - return 0; - } else if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { - return std::numeric_limits<uint32_t>::max(); - } - return capacity + bonusCapacity + varStats[STAT_CAPACITY] + (m_wheelPlayer->getStat(WheelStat_t::CAPACITY) * 100); -} - int32_t Player::getMaxHealth() const { return std::max<int32_t>(1, healthMax + varStats[STAT_MAXHITPOINTS] + m_wheelPlayer->getStat(WheelStat_t::HEALTH)); } @@ -5397,11 +6408,16 @@ uint32_t Player::getMaxMana() const { return std::max<int32_t>(0, manaMax + varStats[STAT_MAXMANAPOINTS] + m_wheelPlayer->getStat(WheelStat_t::MANA)); } +bool Player::hasExtraSwing() { + return lastAttack > 0 && !checkLastAttackWithin(getAttackSpeed()); +} + uint16_t Player::getSkillLevel(skills_t skill) const { auto skillLevel = getLoyaltySkill(skill); skillLevel = std::max<int32_t>(0, skillLevel + varSkills[skill]); - if (auto it = maxValuePerSkill.find(skill); + const auto &maxValuePerSkill = getMaxValuePerSkill(); + if (const auto it = maxValuePerSkill.find(skill); it != maxValuePerSkill.end()) { skillLevel = std::min<int32_t>(it->second, skillLevel); } @@ -5411,12 +6427,12 @@ uint16_t Player::getSkillLevel(skills_t skill) const { skillLevel += m_wheelPlayer->getStat(WheelStat_t::MELEE); skillLevel += m_wheelPlayer->getMajorStatConditional("Battle Instinct", WheelMajor_t::MELEE); } else if (skill == SKILL_DISTANCE) { - skillLevel += m_wheelPlayer->getMajorStatConditional("Positional Tatics", WheelMajor_t::DISTANCE); + skillLevel += m_wheelPlayer->getMajorStatConditional("Positional Tactics", WheelMajor_t::DISTANCE); skillLevel += m_wheelPlayer->getStat(WheelStat_t::DISTANCE); } else if (skill == SKILL_SHIELD) { skillLevel += m_wheelPlayer->getMajorStatConditional("Battle Instinct", WheelMajor_t::SHIELD); } else if (skill == SKILL_MAGLEVEL) { - skillLevel += m_wheelPlayer->getMajorStatConditional("Positional Tatics", WheelMajor_t::MAGIC); + skillLevel += m_wheelPlayer->getMajorStatConditional("Positional Tactics", WheelMajor_t::MAGIC); skillLevel += m_wheelPlayer->getStat(WheelStat_t::MAGIC); } else if (skill == SKILL_LIFE_LEECH_AMOUNT) { skillLevel += m_wheelPlayer->getStat(WheelStat_t::LIFE_LEECH); @@ -5429,7 +6445,7 @@ uint16_t Player::getSkillLevel(skills_t skill) const { skillLevel += m_wheelPlayer->checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_DAMAGE); } - int32_t avatarCritChance = m_wheelPlayer->checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_CHANCE); + const int32_t avatarCritChance = m_wheelPlayer->checkAvatarSkill(WheelAvatarSkill_t::CRITICAL_CHANCE); if (skill == SKILL_CRITICAL_HIT_CHANCE && avatarCritChance > 0) { skillLevel = avatarCritChance; // 100% } @@ -5465,29 +6481,16 @@ time_t Player::getPremiumLastDay() const { return account->getPremiumLastDay(); } +bool Player::isVip() const { + return g_configManager().getBoolean(VIP_SYSTEM_ENABLED) && (getPremiumDays() > 0 || getPremiumLastDay() > getTimeNow()); +} + void Player::setTibiaCoins(int32_t v) { coinBalance = v; } -int32_t Player::getCleavePercent(bool useCharges) const { - int32_t result = cleavePercent; - for (const auto &item : getEquippedItems()) { - const ItemType &it = Item::items[item->getID()]; - if (!it.abilities) { - continue; - } - - const int32_t &cleave_percent = it.abilities->cleavePercent; - if (cleave_percent != 0) { - result += cleave_percent; - uint16_t charges = item->getCharges(); - if (useCharges && charges != 0) { - g_game().transformItem(item, item->getID(), charges - 1); - } - } - } - - return result; +void Player::setCleavePercent(int32_t value) { + cleavePercent = std::max(0, cleavePercent + value); } int32_t Player::getPerfectShotDamage(uint8_t range, bool useCharges) const { @@ -5509,7 +6512,7 @@ int32_t Player::getPerfectShotDamage(uint8_t range, bool useCharges) const { if (itemType.abilities->perfectShotRange == range) { result += itemType.abilities->perfectShotDamage; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5519,18 +6522,29 @@ int32_t Player::getPerfectShotDamage(uint8_t range, bool useCharges) const { return result; } +void Player::setPerfectShotDamage(uint8_t range, int32_t damage) { + int32_t actualDamage = getPerfectShotDamage(range); + const bool aboveZero = (actualDamage != 0); + actualDamage += damage; + if (actualDamage == 0 && aboveZero) { + perfectShot.erase(range); + } else { + perfectShot[range] = actualDamage; + } +} + int32_t Player::getSpecializedMagicLevel(CombatType_t combat, bool useCharges) const { - int32_t result = specializedMagicLevel[combatTypeToIndex(combat)]; + int32_t result = specializedMagicLevel[combatTypeToIndex(combat)] + m_wheelPlayer->getSpecializedMagic(combat); for (const auto &item : getEquippedItems()) { const ItemType &itemType = Item::items[item->getID()]; if (!itemType.abilities) { continue; } - int32_t specialized_magic_level = itemType.abilities->specializedMagicLevel[combatTypeToIndex(combat)]; + const int32_t specialized_magic_level = itemType.abilities->specializedMagicLevel[combatTypeToIndex(combat)]; if (specialized_magic_level > 0) { result += specialized_magic_level; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5540,6 +6554,10 @@ int32_t Player::getSpecializedMagicLevel(CombatType_t combat, bool useCharges) c return result; } +void Player::setSpecializedMagicLevel(CombatType_t combat, int32_t value) { + specializedMagicLevel[combatTypeToIndex(combat)] = std::max(0, specializedMagicLevel[combatTypeToIndex(combat)] + value); +} + int32_t Player::getMagicShieldCapacityFlat(bool useCharges) const { int32_t result = magicShieldCapacityFlat; for (const auto &item : getEquippedItems()) { @@ -5548,10 +6566,10 @@ int32_t Player::getMagicShieldCapacityFlat(bool useCharges) const { continue; } - int32_t magicCapacity = itemType.abilities->magicShieldCapacityFlat; + const int32_t magicCapacity = itemType.abilities->magicShieldCapacityFlat; if (magicCapacity != 0) { result += magicCapacity; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5561,6 +6579,10 @@ int32_t Player::getMagicShieldCapacityFlat(bool useCharges) const { return result; } +void Player::setMagicShieldCapacityFlat(int32_t value) { + magicShieldCapacityFlat += value; +} + int32_t Player::getMagicShieldCapacityPercent(bool useCharges) const { int32_t result = magicShieldCapacityPercent; for (const auto &item : getEquippedItems()) { @@ -5569,10 +6591,10 @@ int32_t Player::getMagicShieldCapacityPercent(bool useCharges) const { continue; } - int32_t magicPercent = itemType.abilities->magicShieldCapacityPercent; + const int32_t magicPercent = itemType.abilities->magicShieldCapacityPercent; if (magicPercent != 0) { result += magicPercent; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5582,6 +6604,10 @@ int32_t Player::getMagicShieldCapacityPercent(bool useCharges) const { return result; } +void Player::setMagicShieldCapacityPercent(int32_t value) { + magicShieldCapacityPercent += value; +} + double_t Player::getReflectPercent(CombatType_t combat, bool useCharges) const { double_t result = reflectPercent[combatTypeToIndex(combat)]; for (const auto &item : getEquippedItems()) { @@ -5593,7 +6619,7 @@ double_t Player::getReflectPercent(CombatType_t combat, bool useCharges) const { double_t reflectPercent = itemType.abilities->reflectPercent[combatTypeToIndex(combat)]; if (reflectPercent != 0) { result += reflectPercent; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5611,10 +6637,10 @@ int32_t Player::getReflectFlat(CombatType_t combat, bool useCharges) const { continue; } - int32_t reflectFlat = itemType.abilities->reflectFlat[combatTypeToIndex(combat)]; + const int32_t reflectFlat = itemType.abilities->reflectFlat[combatTypeToIndex(combat)]; if (reflectFlat != 0) { result += reflectFlat; - uint16_t charges = item->getCharges(); + const uint16_t charges = item->getCharges(); if (useCharges && charges != 0) { g_game().transformItem(item, item->getID(), charges - 1); } @@ -5628,7 +6654,7 @@ void Player::setTransferableTibiaCoins(int32_t v) { coinTransferableBalance = v; } -PartyShields_t Player::getPartyShield(std::shared_ptr<Player> player) { +PartyShields_t Player::getPartyShield(const std::shared_ptr<Player> &player) { if (!player) { return SHIELD_NONE; } @@ -5682,34 +6708,27 @@ PartyShields_t Player::getPartyShield(std::shared_ptr<Player> player) { return SHIELD_NONE; } -bool Player::isInviting(std::shared_ptr<Player> player) const { +bool Player::isInviting(const std::shared_ptr<Player> &player) const { if (!player || !m_party || m_party->getLeader().get() != this) { return false; } return m_party->isPlayerInvited(player); } -bool Player::isPartner(std::shared_ptr<Player> player) const { +bool Player::isPartner(const std::shared_ptr<Player> &player) const { if (!player || !m_party || player.get() == this) { return false; } return m_party == player->m_party; } -bool Player::isGuildMate(std::shared_ptr<Player> player) const { - if (!player || !guild) { - return false; - } - return guild == player->guild; -} - -void Player::sendPlayerPartyIcons(std::shared_ptr<Player> player) { +void Player::sendPlayerPartyIcons(const std::shared_ptr<Player> &player) const { sendPartyCreatureShield(player); sendPartyCreatureSkull(player); } -bool Player::addPartyInvitation(std::shared_ptr<Party> newParty) { - auto it = std::find(invitePartyList.begin(), invitePartyList.end(), newParty); +bool Player::addPartyInvitation(const std::shared_ptr<Party> &newParty) { + auto it = std::ranges::find(invitePartyList, newParty); if (it != invitePartyList.end()) { return false; } @@ -5718,7 +6737,7 @@ bool Player::addPartyInvitation(std::shared_ptr<Party> newParty) { return true; } -void Player::removePartyInvitation(std::shared_ptr<Party> remParty) { +void Player::removePartyInvitation(const std::shared_ptr<Party> &remParty) { std::erase(invitePartyList, remParty); } @@ -5729,12 +6748,12 @@ void Player::clearPartyInvitations() { invitePartyList.clear(); } -GuildEmblems_t Player::getGuildEmblem(std::shared_ptr<Player> player) const { +GuildEmblems_t Player::getGuildEmblem(const std::shared_ptr<Player> &player) const { if (!player) { return GUILDEMBLEM_NONE; } - const auto playerGuild = player->getGuild(); + const auto &playerGuild = player->getGuild(); if (!playerGuild) { return GUILDEMBLEM_NONE; } @@ -5742,19 +6761,44 @@ GuildEmblems_t Player::getGuildEmblem(std::shared_ptr<Player> player) const { if (player->getGuildWarVector().empty()) { if (guild == playerGuild) { return GUILDEMBLEM_MEMBER; - } else { - return GUILDEMBLEM_OTHER; } - } else if (guild == playerGuild) { + return GUILDEMBLEM_OTHER; + } + if (guild == playerGuild) { return GUILDEMBLEM_ALLY; - } else if (isInWar(player)) { + } + if (isInWar(player)) { return GUILDEMBLEM_ENEMY; } return GUILDEMBLEM_NEUTRAL; } -void Player::sendUnjustifiedPoints() { +uint64_t Player::getSpentMana() const { + return manaSpent; +} + +bool Player::hasFlag(PlayerFlags_t flag) const { + return group->flags[static_cast<std::size_t>(flag)]; +} + +void Player::setFlag(PlayerFlags_t flag) const { + group->flags[static_cast<std::size_t>(flag)] = true; +} + +void Player::removeFlag(PlayerFlags_t flag) const { + group->flags[static_cast<std::size_t>(flag)] = false; +} + +std::shared_ptr<BedItem> Player::getBedItem() { + return bedItem; +} + +void Player::setBedItem(std::shared_ptr<BedItem> b) { + bedItem = std::move(b); +} + +void Player::sendUnjustifiedPoints() const { if (client) { double dayKills = 0; double weekKills = 0; @@ -5773,15 +6817,15 @@ void Player::sendUnjustifiedPoints() { } } - bool isRed = getSkull() == SKULL_RED; + const bool isRed = getSkull() == SKULL_RED; auto dayMax = ((isRed ? 2 : 1) * g_configManager().getNumber(DAY_KILLS_TO_RED)); auto weekMax = ((isRed ? 2 : 1) * g_configManager().getNumber(WEEK_KILLS_TO_RED)); auto monthMax = ((isRed ? 2 : 1) * g_configManager().getNumber(MONTH_KILLS_TO_RED)); - uint8_t dayProgress = std::min(std::round(dayKills / dayMax * 100), 100.0); - uint8_t weekProgress = std::min(std::round(weekKills / weekMax * 100), 100.0); - uint8_t monthProgress = std::min(std::round(monthKills / monthMax * 100), 100.0); + const uint8_t dayProgress = std::min(std::round(dayKills / dayMax * 100), 100.0); + const uint8_t weekProgress = std::min(std::round(weekKills / weekMax * 100), 100.0); + const uint8_t monthProgress = std::min(std::round(monthKills / monthMax * 100), 100.0); uint8_t skullDuration = 0; if (skullTicks != 0) { skullDuration = std::floor<uint8_t>(skullTicks / (24 * 60 * 60 * 1000)); @@ -5791,7 +6835,7 @@ void Player::sendUnjustifiedPoints() { } uint8_t Player::getLastMount() const { - int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT); + const int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT); if (value > 0) { return value; } @@ -5799,7 +6843,7 @@ uint8_t Player::getLastMount() const { } uint8_t Player::getCurrentMount() const { - int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT); + const int32_t value = getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT); if (value > 0) { return value; } @@ -5811,26 +6855,23 @@ void Player::setCurrentMount(uint8_t mount) { } bool Player::hasAnyMount() const { - const auto mounts = g_game().mounts.getMounts(); - for (const auto &mount : mounts) { - if (hasMount(mount)) { - return true; - } - } - return false; + const auto &mounts = g_game().mounts->getMounts(); + return std::ranges::any_of(mounts, [&](const auto &mount) { + return hasMount(mount); + }); } uint8_t Player::getRandomMountId() const { std::vector<uint8_t> playerMounts; - const auto mounts = g_game().mounts.getMounts(); + const auto mounts = g_game().mounts->getMounts(); for (const auto &mount : mounts) { if (hasMount(mount)) { - playerMounts.push_back(mount->id); + playerMounts.emplace_back(mount->id); } } - auto playerMountsSize = static_cast<int32_t>(playerMounts.size() - 1); - auto randomIndex = uniform_random(0, std::max<int32_t>(0, playerMountsSize)); + const auto playerMountsSize = static_cast<int32_t>(playerMounts.size() - 1); + const auto randomIndex = uniform_random(0, std::max<int32_t>(0, playerMountsSize)); return playerMounts.at(randomIndex); } @@ -5849,7 +6890,7 @@ bool Player::toggleMount(bool mount) { return false; } - auto tile = getTile(); + const auto &tile = getTile(); if (!g_configManager().getBoolean(TOGGLE_MOUNT_IN_PZ) && !group->access && tile && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { sendCancelMessage(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE); return false; @@ -5870,7 +6911,7 @@ bool Player::toggleMount(bool mount) { currentMountId = getRandomMountId(); } - const auto currentMount = g_game().mounts.getMountByID(currentMountId); + const auto ¤tMount = g_game().mounts->getMountByID(currentMountId); if (!currentMount) { return false; } @@ -5913,7 +6954,7 @@ bool Player::toggleMount(bool mount) { } bool Player::tameMount(uint8_t mountId) { - if (!g_game().mounts.getMountByID(mountId)) { + if (!g_game().mounts->getMountByID(mountId)) { return false; } @@ -5932,7 +6973,7 @@ bool Player::tameMount(uint8_t mountId) { } bool Player::untameMount(uint8_t mountId) { - if (!g_game().mounts.getMountByID(mountId)) { + if (!g_game().mounts->getMountByID(mountId)) { return false; } @@ -5960,7 +7001,7 @@ bool Player::untameMount(uint8_t mountId) { return true; } -bool Player::hasMount(const std::shared_ptr<Mount> mount) const { +bool Player::hasMount(const std::shared_ptr<Mount> &mount) const { if (isAccessPlayer()) { return true; } @@ -5971,7 +7012,7 @@ bool Player::hasMount(const std::shared_ptr<Mount> mount) const { const uint8_t tmpMountId = mount->id - 1; - int32_t value = getStorageValue(PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31)); + const int32_t value = getStorageValue(PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31)); if (value == -1) { return false; } @@ -5980,7 +7021,7 @@ bool Player::hasMount(const std::shared_ptr<Mount> mount) const { } void Player::dismount() { - const auto mount = g_game().mounts.getMountByID(getCurrentMount()); + const auto &mount = g_game().mounts->getMountByID(getCurrentMount()); if (mount && mount->speed > 0) { g_game().changeSpeed(static_self_cast<Player>(), -mount->speed); } @@ -6137,21 +7178,56 @@ bool Player::addOfflineTrainingTries(skills_t skill, uint64_t tries) { return sendUpdate; } +void Player::addOfflineTrainingTime(int32_t addTime) { + offlineTrainingTime = std::min<int32_t>(12 * 3600 * 1000, offlineTrainingTime + addTime); +} + +void Player::removeOfflineTrainingTime(int32_t removeTime) { + offlineTrainingTime = std::max<int32_t>(0, offlineTrainingTime - removeTime); +} + +int32_t Player::getOfflineTrainingTime() const { + return offlineTrainingTime; +} + +int8_t Player::getOfflineTrainingSkill() const { + return offlineTrainingSkill; +} + +void Player::setOfflineTrainingSkill(int8_t skill) { + offlineTrainingSkill = skill; +} + +uint64_t Player::getBankBalance() const { + return bankBalance; +} + +void Player::setBankBalance(uint64_t balance) { + bankBalance = balance; +} + +std::shared_ptr<Town> Player::getTown() const { + return town; +} +void Player::setTown(const std::shared_ptr<Town> &newTown) { + this->town = newTown; +} + bool Player::hasModalWindowOpen(uint32_t modalWindowId) const { - return find(modalWindows.begin(), modalWindows.end(), modalWindowId) != modalWindows.end(); + return std::ranges::find(modalWindows, modalWindowId) != modalWindows.end(); } void Player::onModalWindowHandled(uint32_t modalWindowId) { std::erase(modalWindows, modalWindowId); } -void Player::sendModalWindow(const ModalWindow &modalWindow) { - if (!client) { - return; +const Position &Player::getTemplePosition() const { + if (!town) { + static auto emptyPosition = Position(); + return emptyPosition; } - modalWindows.emplace_back(modalWindow.id); - client->sendModalWindow(modalWindow); + return town->getTemplePosition(); } void Player::clearModalWindows() { @@ -6183,1698 +7259,2802 @@ uint16_t Player::getHelpers() const { return 0u; } -void Player::sendClosePrivate(uint16_t channelId) { - if (channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY) { - g_chat().removeUserFromChannel(getPlayer(), channelId); +void Player::sendImbuementResult(const std::string &message) const { + if (client) { + client->sendImbuementResult(message); } +} +void Player::closeImbuementWindow() const { if (client) { - client->sendClosePrivate(channelId); + client->closeImbuementWindow(); } } -void Player::sendIcons() { - if (!client) { - return; +void Player::sendPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos) const { + if (client) { + client->sendPodiumWindow(podium, position, itemId, stackpos); } +} - // Iterates over the Bakragore icons to check if the player has any - IconBakragore iconBakragore = IconBakragore::None; - for (auto icon : magic_enum::enum_values<IconBakragore>()) { - if (icon == IconBakragore::None) { - continue; - } - - const auto &condition = getCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, magic_enum::enum_integer(icon)); - if (condition) { - g_logger().debug("[{}] found active condition Bakragore with subId {}", __FUNCTION__, magic_enum::enum_integer(icon)); - iconBakragore = icon; - } +void Player::sendCloseContainer(uint8_t cid) const { + if (client) { + client->sendCloseContainer(cid); } +} - // Remove the last icon so that Bakragore's is added - auto iconSet = getClientIcons(); - if (iconSet.size() >= 9 && iconBakragore != IconBakragore::None) { - std::vector<PlayerIcon> tempVector(iconSet.begin(), iconSet.end()); - tempVector.pop_back(); - iconSet = std::unordered_set<PlayerIcon>(tempVector.begin(), tempVector.end()); +void Player::sendChannel(uint16_t channelId, const std::string &channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) const { + if (client) { + client->sendChannel(channelId, channelName, channelUsers, invitedUsers); } - - client->sendIcons(iconSet, iconBakragore); } -void Player::sendIconBakragore(const IconBakragore icon) { +void Player::sendTutorial(uint8_t tutorialId) const { if (client) { - client->sendIconBakragore(icon); + client->sendTutorial(tutorialId); } } -void Player::removeBakragoreIcons() { - for (auto icon : magic_enum::enum_values<IconBakragore>()) { - if (hasCondition(CONDITION_BAKRAGORE, enumToValue(icon))) { - removeCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, true); - } +void Player::sendAddMarker(const Position &pos, uint8_t markType, const std::string &desc) const { + if (client) { + client->sendAddMarker(pos, markType, desc); } } -void Player::removeBakragoreIcon(const IconBakragore icon) { - if (hasCondition(CONDITION_BAKRAGORE, enumToValue(icon))) { - removeCondition(CONDITION_BAKRAGORE, CONDITIONID_DEFAULT, true); +void Player::sendItemInspection(uint16_t itemId, uint8_t itemCount, const std::shared_ptr<Item> &item, bool cyclopedia) const { + if (client) { + client->sendItemInspection(itemId, itemCount, item, cyclopedia); } } -void Player::sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, std::vector<std::pair<Achievement, uint32_t>> achievementsUnlocked) { +void Player::sendCyclopediaCharacterNoData(CyclopediaCharacterInfoType_t characterInfoType, uint8_t errorCode) const { if (client) { - client->sendCyclopediaCharacterAchievements(secretsUnlocked, achievementsUnlocked); + client->sendCyclopediaCharacterNoData(characterInfoType, errorCode); } } -uint64_t Player::getMoney() const { - std::vector<std::shared_ptr<Container>> containers; - uint64_t moneyCount = 0; - - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - std::shared_ptr<Item> item = inventory[i]; - if (!item) { - continue; - } - - std::shared_ptr<Container> container = item->getContainer(); - if (container) { - containers.push_back(container); - } else { - moneyCount += item->getWorth(); - } +void Player::sendCyclopediaCharacterBaseInformation() const { + if (client) { + client->sendCyclopediaCharacterBaseInformation(); } +} - size_t i = 0; - while (i < containers.size()) { - std::shared_ptr<Container> container = containers[i++]; - for (const std::shared_ptr<Item> &item : container->getItemList()) { - std::shared_ptr<Container> tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); - } else { - moneyCount += item->getWorth(); - } - } +void Player::sendCyclopediaCharacterGeneralStats() const { + if (client) { + client->sendCyclopediaCharacterGeneralStats(); } - return moneyCount; } -std::pair<uint64_t, uint64_t> Player::getForgeSliversAndCores() const { - uint64_t sliverCount = 0; - uint64_t coreCount = 0; - - // Check items from inventory - for (const auto &item : getAllInventoryItems()) { - if (!item) { - continue; - } +void Player::sendCyclopediaCharacterCombatStats() const { + if (client) { + client->sendCyclopediaCharacterCombatStats(); + } +} - sliverCount += item->getForgeSlivers(); - coreCount += item->getForgeCores(); +void Player::sendCyclopediaCharacterRecentDeaths(uint16_t page, uint16_t pages, const std::vector<RecentDeathEntry> &entries) const { + if (client) { + client->sendCyclopediaCharacterRecentDeaths(page, pages, entries); } +} - // Check items from stash - for (StashItemList stashToSend = getStashItems(); - auto [itemId, itemCount] : stashToSend) { - if (itemId == ITEM_FORGE_SLIVER) { - sliverCount += itemCount; - } - if (itemId == ITEM_FORGE_CORE) { - coreCount += itemCount; - } +void Player::sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t pages, const std::vector<RecentPvPKillEntry> &entries) const { + if (client) { + client->sendCyclopediaCharacterRecentPvPKills(page, pages, entries); } +} - return std::make_pair(sliverCount, coreCount); +void Player::sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, const std::vector<std::pair<Achievement, uint32_t>> &achievementsUnlocked) const { + if (client) { + client->sendCyclopediaCharacterAchievements(secretsUnlocked, achievementsUnlocked); + } } -size_t Player::getMaxDepotItems() const { - if (group->maxDepotItems != 0) { - return group->maxDepotItems; - } else if (isPremium()) { - return g_configManager().getNumber(PREMIUM_DEPOT_LIMIT); +void Player::sendCyclopediaCharacterItemSummary(const ItemsTierCountList &inventoryItems, const ItemsTierCountList &storeInboxItems, const StashItemList &supplyStashItems, const ItemsTierCountList &depotBoxItems, const ItemsTierCountList &inboxItems) const { + if (client) { + client->sendCyclopediaCharacterItemSummary(inventoryItems, storeInboxItems, supplyStashItems, depotBoxItems, inboxItems); } - return g_configManager().getNumber(FREE_DEPOT_LIMIT); } -std::vector<std::shared_ptr<Condition>> Player::getMuteConditions() const { - std::vector<std::shared_ptr<Condition>> muteConditions; - muteConditions.reserve(conditions.size()); +void Player::sendCyclopediaCharacterOutfitsMounts() const { + if (client) { + client->sendCyclopediaCharacterOutfitsMounts(); + } +} - for (const std::shared_ptr<Condition> &condition : conditions) { - if (condition->getTicks() <= 0) { - continue; - } +void Player::sendCyclopediaCharacterStoreSummary() const { + if (client) { + client->sendCyclopediaCharacterStoreSummary(); + } +} - ConditionType_t type = condition->getType(); - if (type != CONDITION_MUTED && type != CONDITION_CHANNELMUTEDTICKS && type != CONDITION_YELLTICKS) { - continue; - } +void Player::sendCyclopediaCharacterInspection() const { + if (client) { + client->sendCyclopediaCharacterInspection(); + } +} - muteConditions.emplace_back(condition); +void Player::sendCyclopediaCharacterBadges() const { + if (client) { + client->sendCyclopediaCharacterBadges(); } - return muteConditions; } -void Player::setGuild(const std::shared_ptr<Guild> newGuild) { - if (newGuild == guild) { - return; +void Player::sendCyclopediaCharacterTitles() const { + if (client) { + client->sendCyclopediaCharacterTitles(); } +} - if (guild) { - guild->removeMember(static_self_cast<Player>()); - guild = nullptr; +void Player::sendHighscoresNoData() const { + if (client) { + client->sendHighscoresNoData(); } +} - guildNick.clear(); - guildRank = nullptr; +void Player::sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) const { + if (client) { + client->sendHighscores(characters, categoryId, vocationId, page, pages, updateTimer); + } +} - if (newGuild) { - const auto rank = newGuild->getRankByLevel(1); - if (!rank) { - return; - } +void Player::addAsyncOngoingTask(uint64_t flags) { + asyncOngoingTasks |= flags; +} - guild = newGuild; - guildRank = rank; - newGuild->addMember(static_self_cast<Player>()); - } +bool Player::hasAsyncOngoingTask(uint64_t flags) const { + return (asyncOngoingTasks & flags); } -void Player::updateRegeneration() { - if (!vocation) { - return; +void Player::resetAsyncOngoingTask(uint64_t flags) { + asyncOngoingTasks &= ~flags; +} + +void Player::sendEnterWorld() const { + if (client) { + client->sendEnterWorld(); } +} - std::shared_ptr<Condition> condition = getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); - if (condition) { - condition->setParam(CONDITION_PARAM_HEALTHGAIN, vocation->getHealthGainAmount()); - condition->setParam(CONDITION_PARAM_HEALTHTICKS, vocation->getHealthGainTicks()); - condition->setParam(CONDITION_PARAM_MANAGAIN, vocation->getManaGainAmount()); - condition->setParam(CONDITION_PARAM_MANATICKS, vocation->getManaGainTicks()); +void Player::sendFightModes() const { + if (client) { + client->sendFightModes(); } } -// User Interface action exhaustion -bool Player::isUIExhausted(uint32_t exhaustionTime /*= 250*/) const { - return (OTSYS_TIME() - lastUIInteraction < exhaustionTime); +void Player::sendNetworkMessage(const NetworkMessage &message) const { + if (client) { + client->writeToOutputBuffer(message); + } } -void Player::updateUIExhausted() { - lastUIInteraction = OTSYS_TIME(); +void Player::receivePing() { + lastPong = OTSYS_TIME(); } -void Player::setImmuneFear() { - m_fearCondition.first = CONDITION_FEARED; - m_fearCondition.second = OTSYS_TIME() + 10000; +void Player::sendOpenStash(bool isNpc) const { + if (client && ((getLastDepotId() != -1) || isNpc)) { + client->sendOpenStash(); + } } -bool Player::isImmuneFear() const { - uint64_t timenow = OTSYS_TIME(); - return (m_fearCondition.first == CONDITION_FEARED) && (timenow <= m_fearCondition.second); +void Player::sendTakeScreenshot(Screenshot_t screenshotType) const { + if (client) { + client->sendTakeScreenshot(screenshotType); + } } -uint64_t Player::getItemCustomPrice(uint16_t itemId, bool buyPrice /* = false*/) const { - auto it = itemPriceMap.find(itemId); - if (it != itemPriceMap.end()) { - return it->second; +void Player::onThink(uint32_t interval) { + Creature::onThink(interval); + + sendPing(); + + MessageBufferTicks += interval; + if (MessageBufferTicks >= 1500) { + MessageBufferTicks = 0; + addMessageBuffer(); } - std::map<uint16_t, uint64_t> itemMap { { itemId, 1 } }; - return g_game().getItemMarketPrice(itemMap, buyPrice); -} + // Transcendance (avatar trigger) + triggerTranscendance(); + // Momentum (cooldown resets) + triggerMomentum(); + const auto &playerTile = getTile(); + const bool vipStaysOnline = isVip() && g_configManager().getBoolean(VIP_STAY_ONLINE); + idleTime += interval; + if (playerTile && !playerTile->hasFlag(TILESTATE_NOLOGOUT) && !isAccessPlayer() && !isExerciseTraining() && !vipStaysOnline) { + const int32_t kickAfterMinutes = g_configManager().getNumber(KICK_AFTER_MINUTES); + if (idleTime > (kickAfterMinutes * 60000) + 60000) { + removePlayer(true); + } else if (client && idleTime == 60000 * kickAfterMinutes) { + std::ostringstream ss; + ss << "There was no variation in your behaviour for " << kickAfterMinutes << " minutes. You will be disconnected in one minute if there is no change in your actions until then."; + client->sendTextMessage(TextMessage(MESSAGE_ADMINISTRATOR, ss.str())); + } + } -uint16_t Player::getFreeBackpackSlots() const { - std::shared_ptr<Thing> thing = getThing(CONST_SLOT_BACKPACK); - if (!thing) { - return 0; + if (g_game().getWorldType() != WORLD_TYPE_PVP_ENFORCED) { + checkSkullTicks(interval / 1000); } - std::shared_ptr<Container> backpack = thing->getContainer(); - if (!backpack) { - return 0; + addOfflineTrainingTime(interval); + if (lastStatsTrainingTime != getOfflineTrainingTime() / 60 / 1000) { + sendStats(); } - uint16_t counter = std::max<uint16_t>(0, backpack->getFreeSlots()); + // Wheel of destiny major spells + wheel()->onThink(); - return counter; + g_callbacks().executeCallback(EventCallback_t::playerOnThink, &EventCallback::playerOnThink, getPlayer(), interval); } -void Player::addItemImbuementStats(const Imbuement* imbuement) { - bool requestUpdate = false; - // Check imbuement skills - for (int32_t skill = SKILL_FIRST; skill <= SKILL_LAST; ++skill) { - if (imbuement->skills[skill]) { - requestUpdate = true; - setVarSkill(static_cast<skills_t>(skill), imbuement->skills[skill]); - } +void Player::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link) { + if (link == LINK_OWNER) { + // calling movement scripts + g_moveEvents().onPlayerEquip(getPlayer(), thing->getItem(), static_cast<Slots_t>(index), false); } - // Check imbuement magic level - for (int32_t stat = STAT_FIRST; stat <= STAT_LAST; ++stat) { - if (imbuement->stats[stat]) { - requestUpdate = true; - setVarStats(static_cast<stats_t>(stat), imbuement->stats[stat]); + bool requireListUpdate = true; + if (link == LINK_OWNER || link == LINK_TOPPARENT) { + const auto &item = oldParent ? oldParent->getItem() : nullptr; + const auto &container = item ? item->getContainer() : nullptr; + if (container) { + requireListUpdate = container->getHoldingPlayer() != getPlayer(); + } else { + requireListUpdate = oldParent != getPlayer(); } - } - // Add imbuement speed - if (imbuement->speed != 0) { - g_game().changeSpeed(static_self_cast<Player>(), imbuement->speed); + updateInventoryWeight(); + updateItemsLight(); + sendInventoryIds(); + sendStats(); } - // Add imbuement capacity - if (imbuement->capacity != 0) { - requestUpdate = true; - bonusCapacity = (capacity * imbuement->capacity) / 100; - } + if (const auto &item = thing->getItem()) { + if (const auto &container = item->getContainer()) { + onSendContainer(container); + } - if (requestUpdate) { - sendStats(); - sendSkills(); + if (shopOwner && !scheduledSaleUpdate && requireListUpdate) { + updateSaleShopList(item); + } + } else if (const auto &creature = thing->getCreature()) { + if (creature == getPlayer()) { + // check containers + std::vector<std::shared_ptr<Container>> containers; + + for (const auto &[containerId, containerInfo] : openContainers) { + const auto &container = containerInfo.container; + if (container == nullptr) { + continue; + } + + if (!Position::areInRange<1, 1, 0>(container->getPosition(), getPosition())) { + containers.emplace_back(container); + } + } + + for (const auto &container : containers) { + autoCloseContainers(container); + } + } } } -void Player::removeItemImbuementStats(const Imbuement* imbuement) { - if (!imbuement) { +void Player::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link) { + if (!thing) { return; } - bool requestUpdate = false; + const auto copyThing = thing; + const auto copyNewParent = newParent; - for (int32_t skill = SKILL_FIRST; skill <= SKILL_LAST; ++skill) { - if (imbuement->skills[skill]) { - requestUpdate = true; - setVarSkill(static_cast<skills_t>(skill), -imbuement->skills[skill]); + if (link == LINK_OWNER) { + if (const auto &item = copyThing->getItem()) { + g_moveEvents().onPlayerDeEquip(getPlayer(), item, static_cast<Slots_t>(index)); } } + bool requireListUpdate = true; - // Check imbuement magic level - for (int32_t stat = STAT_FIRST; stat <= STAT_LAST; ++stat) { - if (imbuement->stats[stat]) { - requestUpdate = true; - setVarStats(static_cast<stats_t>(stat), -imbuement->stats[stat]); + if (link == LINK_OWNER || link == LINK_TOPPARENT) { + const auto &item = copyNewParent ? copyNewParent->getItem() : nullptr; + const auto &container = item ? item->getContainer() : nullptr; + if (container) { + requireListUpdate = container->getHoldingPlayer() != getPlayer(); + } else { + requireListUpdate = copyNewParent != getPlayer(); } - } - // Remove imbuement speed - if (imbuement->speed != 0) { - g_game().changeSpeed(static_self_cast<Player>(), -imbuement->speed); + updateInventoryWeight(); + updateItemsLight(); + sendInventoryIds(); + sendStats(); } - // Remove imbuement capacity - if (imbuement->capacity != 0) { - requestUpdate = true; - bonusCapacity = 0; + if (const auto &item = copyThing->getItem()) { + if (const auto &container = item->getContainer()) { + checkLootContainers(container); + + if (container->isRemoved() || !Position::areInRange<1, 1, 0>(getPosition(), container->getPosition())) { + autoCloseContainers(container); + } else if (container->getTopParent() == getPlayer()) { + onSendContainer(container); + } else if (const auto &topContainer = std::dynamic_pointer_cast<Container>(container->getTopParent())) { + if (const auto &depotChest = std::dynamic_pointer_cast<DepotChest>(topContainer)) { + bool isOwner = false; + + for (const auto &[depotId, depotChestMap] : depotChests) { + if (depotId == 0) { + continue; + } + + if (depotChestMap == depotChest) { + isOwner = true; + onSendContainer(container); + } + } + + if (!isOwner) { + autoCloseContainers(container); + } + } else { + onSendContainer(container); + } + } else { + autoCloseContainers(container); + } + } + + // force list update if item exists tier + if (item->getTier() > 0 && !requireListUpdate) { + requireListUpdate = true; + } + + if (shopOwner && !scheduledSaleUpdate && requireListUpdate) { + updateSaleShopList(item); + } } +} - if (requestUpdate) { - sendStats(); - sendSkills(); +void Player::sendUpdateTile(const std::shared_ptr<Tile> &updateTile, const Position &pos) const { + if (client) { + client->sendUpdateTile(updateTile, pos); } } -void Player::updateImbuementTrackerStats() const { - if (imbuementTrackerWindowOpen) { - g_game().playerRequestInventoryImbuements(getID(), true); +void Player::sendChannelMessage(const std::string &author, const std::string &text, SpeakClasses type, uint16_t channel) const { + if (client) { + client->sendChannelMessage(author, text, type, channel); } } -bool Player::addItemFromStash(uint16_t itemId, uint32_t itemCount) { - uint32_t stackCount = 100u; +void Player::sendChannelEvent(uint16_t channelId, const std::string &playerName, ChannelEvent_t channelEvent) const { + if (client) { + client->sendChannelEvent(channelId, playerName, channelEvent); + } +} - while (itemCount > 0) { - auto addValue = itemCount > stackCount ? stackCount : itemCount; - itemCount -= addValue; - std::shared_ptr<Item> newItem = Item::CreateItem(itemId, addValue); +void Player::sendCreatureAppear(const std::shared_ptr<Creature> &creature, const Position &pos, bool isLogin) { + if (!creature) { + return; + } - if (!g_game().tryRetrieveStashItems(static_self_cast<Player>(), newItem)) { - g_game().internalPlayerAddItem(static_self_cast<Player>(), newItem, true); - } + auto tile = creature->getTile(); + if (!tile) { + return; } - // This check is necessary because we need to block it when we retrieve an item from depot search. - if (!isDepotSearchOpenOnItem(itemId)) { - sendOpenStash(); + if (client) { + client->sendAddCreature(creature, pos, tile->getStackposOfCreature(static_self_cast<Player>(), creature), isLogin); } +} - return true; +void Player::sendCreatureMove(const std::shared_ptr<Creature> &creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport) const { + if (client) { + client->sendMoveCreature(creature, newPos, newStackPos, oldPos, oldStackPos, teleport); + } } -void sendStowItems(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &stowItem, StashContainerList &itemDict) { - if (stowItem->getID() == item->getID()) { - itemDict.push_back(std::pair<std::shared_ptr<Item>, uint32_t>(stowItem, stowItem->getItemCount())); +void Player::sendCreatureTurn(const std::shared_ptr<Creature> &creature) { + if (!creature) { + return; } - if (auto container = stowItem->getContainer()) { - for (const auto &stowable_it : container->getStowableItems()) { - if ((stowable_it.first)->getID() == item->getID()) { - itemDict.push_back(stowable_it); - } + auto tile = creature->getTile(); + if (!tile) { + return; + } + + if (client && canSeeCreature(creature)) { + int32_t stackpos = tile->getStackposOfCreature(static_self_cast<Player>(), creature); + if (stackpos != -1) { + client->sendCreatureTurn(creature, stackpos); } } } -void Player::stowItem(std::shared_ptr<Item> item, uint32_t count, bool allItems) { - if (!item || !item->isItemStorable()) { - sendCancelMessage("This item cannot be stowed here."); - return; +void Player::sendCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, const Position* pos) const { + if (client) { + client->sendCreatureSay(creature, type, text, pos); } +} - StashContainerList itemDict; - if (allItems) { - if (!item->isInsideDepot(true)) { - // Stow "all items" from player backpack - if (auto backpack = getInventoryItem(CONST_SLOT_BACKPACK)) { - sendStowItems(item, backpack, itemDict); - } - - // Stow "all items" from loot pouch - auto itemParent = item->getParent(); - auto lootPouch = itemParent->getItem(); - if (itemParent && lootPouch && lootPouch->getID() == ITEM_GOLD_POUCH) { - sendStowItems(item, lootPouch, itemDict); - } - } - - // Stow locker items - std::shared_ptr<DepotLocker> depotLocker = getDepotLocker(getLastDepotId()); - auto [itemVector, itemMap] = requestLockerItems(depotLocker); - for (const auto &lockerItem : itemVector) { - if (lockerItem == nullptr) { - break; - } +void Player::sendCreatureReload(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->reloadCreature(creature); + } +} - if (item->isInsideDepot(true)) { - sendStowItems(item, lockerItem, itemDict); - } - } - } else if (item->getContainer()) { - itemDict = item->getContainer()->getStowableItems(); - for (const std::shared_ptr<Item> &containerItem : item->getContainer()->getItems(true)) { - uint32_t depotChest = g_configManager().getNumber(DEPOTCHEST); - bool validDepot = depotChest > 0 && depotChest < 21; - if (g_configManager().getBoolean(STASH_MOVING) && containerItem && !containerItem->isStackable() && validDepot) { - g_game().internalMoveItem(containerItem->getParent(), getDepotChest(depotChest, true), INDEX_WHEREEVER, containerItem, containerItem->getItemCount(), nullptr); - movedItems++; - moved = true; - } - } - } else { - itemDict.emplace_back(item, count); +void Player::sendPrivateMessage(const std::shared_ptr<Player> &speaker, SpeakClasses type, const std::string &text) const { + if (client) { + client->sendPrivateMessage(speaker, type, text); } +} - if (itemDict.empty()) { - sendCancelMessage("There is no stowable items on this container."); - return; +void Player::sendCreatureSquare(const std::shared_ptr<Creature> &creature, SquareColor_t color) const { + if (client) { + client->sendCreatureSquare(creature, color); } +} - stashContainer(itemDict); +void Player::sendCreatureChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) const { + if (client) { + client->sendCreatureOutfit(creature, outfit); + } } -void Player::openPlayerContainers() { - std::vector<std::pair<uint8_t, std::shared_ptr<Container>>> openContainersList; +void Player::sendCreatureChangeVisible(const std::shared_ptr<Creature> &creature, bool visible) { + if (!client || !creature) { + return; + } - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - std::shared_ptr<Item> item = inventory[i]; - if (!item) { - continue; + if (creature->getPlayer()) { + if (visible) { + client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); + } else { + static Outfit_t outfit; + client->sendCreatureOutfit(creature, outfit); + } + } else if (canSeeInvisibility()) { + client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); + } else { + auto tile = creature->getTile(); + if (!tile) { + return; + } + int32_t stackpos = tile->getStackposOfCreature(static_self_cast<Player>(), creature); + if (stackpos == -1) { + return; } - std::shared_ptr<Container> itemContainer = item->getContainer(); - if (itemContainer) { - auto cid = item->getAttribute<int64_t>(ItemAttribute_t::OPENCONTAINER); - if (cid > 0) { - openContainersList.emplace_back(cid, itemContainer); - } - for (ContainerIterator it = itemContainer->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Container> subContainer = (*it)->getContainer(); - if (subContainer) { - auto subcid = (*it)->getAttribute<uint8_t>(ItemAttribute_t::OPENCONTAINER); - if (subcid > 0) { - openContainersList.emplace_back(subcid, subContainer); - } - } - } + if (visible) { + client->sendAddCreature(creature, creature->getPosition(), stackpos, false); + } else { + client->sendRemoveTileThing(creature->getPosition(), stackpos); } } +} - std::sort(openContainersList.begin(), openContainersList.end(), [](const std::pair<uint8_t, std::shared_ptr<Container>> &left, const std::pair<uint8_t, std::shared_ptr<Container>> &right) { - return left.first < right.first; - }); - - for (auto &it : openContainersList) { - addContainer(it.first - 1, it.second); - onSendContainer(it.second); +void Player::sendCreatureLight(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendCreatureLight(creature); } } -void Player::initializePrey() { - if (preys.empty()) { - for (uint8_t slotId = PreySlot_First; slotId <= PreySlot_Last; slotId++) { - auto slot = std::make_unique<PreySlot>(static_cast<PreySlot_t>(slotId)); - if (!g_configManager().getBoolean(PREY_ENABLED)) { - slot->state = PreyDataState_Inactive; - } else if (slot->id == PreySlot_Three && !g_configManager().getBoolean(PREY_FREE_THIRD_SLOT)) { - slot->state = PreyDataState_Locked; - } else if (slot->id == PreySlot_Two && !isPremium()) { - slot->state = PreyDataState_Locked; - } else { - slot->state = PreyDataState_Selection; - slot->reloadMonsterGrid(getPreyBlackList(), getLevel()); - } - - setPreySlotClass(slot); - } +void Player::sendCreatureIcon(const std::shared_ptr<Creature> &creature) const { + if (client && !client->oldProtocol) { + client->sendCreatureIcon(creature); } } -void Player::removePreySlotById(PreySlot_t slotid) { - auto it = std::remove_if(preys.begin(), preys.end(), [slotid](const std::unique_ptr<PreySlot> &preyIt) { - return preyIt->id == slotid; - }); +void Player::sendUpdateCreature(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendUpdateCreature(creature); + } +} - preys.erase(it, preys.end()); +void Player::sendCreatureWalkthrough(const std::shared_ptr<Creature> &creature, bool walkthrough) const { + if (client) { + client->sendCreatureWalkthrough(creature, walkthrough); + } } -void Player::initializeTaskHunting() { - if (taskHunting.empty()) { - for (uint8_t slotId = PreySlot_First; slotId <= PreySlot_Last; slotId++) { - auto slot = std::make_unique<TaskHuntingSlot>(static_cast<PreySlot_t>(slotId)); - if (!g_configManager().getBoolean(TASK_HUNTING_ENABLED)) { - slot->state = PreyTaskDataState_Inactive; - } else if (slot->id == PreySlot_Three && !g_configManager().getBoolean(TASK_HUNTING_FREE_THIRD_SLOT)) { - slot->state = PreyTaskDataState_Locked; - } else if (slot->id == PreySlot_Two && !isPremium()) { - slot->state = PreyTaskDataState_Locked; - } else { - slot->state = PreyTaskDataState_Selection; - slot->reloadMonsterGrid(getTaskHuntingBlackList(), getLevel()); - } +void Player::sendCreatureShield(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->sendCreatureShield(creature); + } +} - setTaskHuntingSlotClass(slot); - } +void Player::sendCreatureType(const std::shared_ptr<Creature> &creature, uint8_t creatureType) const { + if (client) { + client->sendCreatureType(creature, creatureType); } +} - if (client && g_configManager().getBoolean(TASK_HUNTING_ENABLED) && !client->oldProtocol) { - client->writeToOutputBuffer(g_ioprey().getTaskHuntingBaseDate()); +void Player::sendSpellCooldown(uint16_t spellId, uint32_t time) const { + if (client) { + client->sendSpellCooldown(spellId, time); } } -std::string Player::getBlessingsName() const { - std::vector<std::string> blessingNames; - for (auto bless : magic_enum::enum_values<Blessings>()) { - if (hasBlessing(enumToValue(bless))) { - std::string name = toStartCaseWithSpace(magic_enum::enum_name(bless).data()); - blessingNames.emplace_back(name); - } +void Player::sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time) const { + if (client) { + client->sendSpellGroupCooldown(groupId, time); } +} - std::ostringstream os; - if (!blessingNames.empty()) { - // Join all elements but the last with ", " and add the last one with " and " - for (size_t i = 0; i < blessingNames.size() - 1; ++i) { - os << blessingNames[i] << ", "; - } - if (blessingNames.size() > 1) { - os << "and "; - } - os << blessingNames.back() << "."; +void Player::sendUseItemCooldown(uint32_t time) const { + if (client) { + client->sendUseItemCooldown(time); } +} - return os.str(); +void Player::reloadCreature(const std::shared_ptr<Creature> &creature) const { + if (client) { + client->reloadCreature(creature); + } } -bool Player::isCreatureUnlockedOnTaskHunting(const std::shared_ptr<MonsterType> mtype) const { - if (!mtype) { - return false; +void Player::sendModalWindow(const ModalWindow &modalWindow) { + if (!client) { + return; } - return getBestiaryKillCount(mtype->info.raceid) >= mtype->info.bestiaryToUnlock; + modalWindows.emplace_back(modalWindow.id); + client->sendModalWindow(modalWindow); } -void Player::triggerMomentum() { - auto item = getInventoryItem(CONST_SLOT_HEAD); +// container - double_t chance = 0; - if (item) { - chance += item->getMomentumChance(); +void Player::closeAllExternalContainers() { + if (openContainers.empty()) { + return; } - chance += m_wheelPlayer->getBonusData().momentum; - double_t randomChance = uniform_random(0, 10000) / 100.; - if (getZoneType() != ZONE_PROTECTION && hasCondition(CONDITION_INFIGHT) && ((OTSYS_TIME() / 1000) % 2) == 0 && chance > 0 && randomChance < chance) { - bool triggered = false; - auto it = conditions.begin(); - while (it != conditions.end()) { - auto condItem = *it; - ConditionType_t type = condItem->getType(); - auto maxu16 = std::numeric_limits<uint16_t>::max(); - auto checkSpellId = condItem->getSubId(); - auto spellId = checkSpellId > maxu16 ? 0u : static_cast<uint16_t>(checkSpellId); - int32_t ticks = condItem->getTicks(); - int32_t newTicks = (ticks <= 2000) ? 0 : ticks - 2000; - triggered = true; - if (type == CONDITION_SPELLCOOLDOWN || (type == CONDITION_SPELLGROUPCOOLDOWN && spellId > SPELLGROUP_SUPPORT)) { - condItem->setTicks(newTicks); - type == CONDITION_SPELLGROUPCOOLDOWN ? sendSpellGroupCooldown(static_cast<SpellGroup_t>(spellId), newTicks) : sendSpellCooldown(spellId, newTicks); - } - ++it; + std::vector<std::shared_ptr<Container>> containerToClose; + for (const auto &[containerId, containerInfo] : openContainers) { + const auto &container = containerInfo.container; + if (!container) { + continue; } - if (triggered) { - g_game().addMagicEffect(getPosition(), CONST_ME_HOURGLASS); - sendTextMessage(MESSAGE_ATTENTION, "Momentum was triggered."); + + if (container->getHoldingPlayer() != getPlayer()) { + containerToClose.emplace_back(container); } } -} -void Player::clearCooldowns() { - auto it = conditions.begin(); - while (it != conditions.end()) { - auto condItem = *it; - ConditionType_t type = condItem->getType(); - auto maxu16 = std::numeric_limits<uint16_t>::max(); - auto checkSpellId = condItem->getSubId(); - auto spellId = checkSpellId > maxu16 ? 0u : static_cast<uint16_t>(checkSpellId); - if (type == CONDITION_SPELLCOOLDOWN || type == CONDITION_SPELLGROUPCOOLDOWN) { - condItem->setTicks(0); - type == CONDITION_SPELLGROUPCOOLDOWN ? sendSpellGroupCooldown(static_cast<SpellGroup_t>(spellId), 0) : sendSpellCooldown(spellId, 0); - } - ++it; + for (const auto &container : containerToClose) { + autoCloseContainers(container); } } -void Player::triggerTranscendance() { - if (wheel()->getOnThinkTimer(WheelOnThink_t::AVATAR_FORGE) > OTSYS_TIME()) { +// container + +void Player::sendAddContainerItem(const std::shared_ptr<Container> &container, std::shared_ptr<Item> item) { + if (!client) { return; } - auto item = getInventoryItem(CONST_SLOT_LEGS); - if (item == nullptr) { + if (!container) { return; } - double_t chance = item->getTranscendenceChance(); - double_t randomChance = uniform_random(0, 10000) / 100.; - if (getZoneType() != ZONE_PROTECTION && checkLastAggressiveActionWithin(2000) && ((OTSYS_TIME() / 1000) % 2) == 0 && chance > 0 && randomChance < chance) { - int64_t duration = g_configManager().getNumber(TRANSCENDANCE_AVATAR_DURATION); - auto outfitCondition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)->static_self_cast<ConditionOutfit>(); - Outfit_t outfit; - outfit.lookType = getVocation()->getAvatarLookType(); - outfitCondition->setOutfit(outfit); - addCondition(outfitCondition); - wheel()->setOnThinkTimer(WheelOnThink_t::AVATAR_FORGE, OTSYS_TIME() + duration); - g_game().addMagicEffect(getPosition(), CONST_ME_AVATAR_APPEAR); - - sendSkills(); - sendStats(); - sendBasicData(); - - sendTextMessage(MESSAGE_ATTENTION, "Transcendance was triggered."); - - // Send player data after transcendance timer expire - const auto &task = createPlayerTask( - std::max<uint32_t>(SCHEDULER_MINTICKS, duration), - [playerId = getID()] { - auto player = g_game().getPlayerByID(playerId); - if (player) { - player->sendSkills(); - player->sendStats(); - player->sendBasicData(); - } - }, - __FUNCTION__ - ); - g_dispatcher().scheduleEvent(task); + for (const auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container != container) { + continue; + } - wheel()->sendGiftOfLifeCooldown(); - g_game().reloadCreature(getPlayer()); + uint16_t slot = containerInfo.index; + if (container->getID() == ITEM_BROWSEFIELD) { + const uint16_t containerSize = container->size() - 1; + const uint16_t pageEnd = containerInfo.index + container->capacity() - 1; + if (containerSize > pageEnd) { + slot = pageEnd; + item = container->getItemByIndex(pageEnd); + } else { + slot = containerSize; + } + } else if (containerInfo.index >= container->capacity()) { + item = container->getItemByIndex(containerInfo.index - 1); + } + client->sendAddContainerItem(containerId, slot, item); } } -/******************************************************************************* - * Depot search system - ******************************************************************************/ -void Player::requestDepotItems() { - ItemsTierCountList itemMap; - uint16_t count = 0; - std::shared_ptr<DepotLocker> depotLocker = getDepotLocker(getLastDepotId()); - if (!depotLocker) { +void Player::sendUpdateContainerItem(const std::shared_ptr<Container> &container, uint16_t slot, const std::shared_ptr<Item> &newItem) { + if (!client) { return; } - for (const std::shared_ptr<Item> &locker : depotLocker->getItemList()) { - std::shared_ptr<Container> c = locker->getContainer(); - if (!c || c->empty()) { + for (const auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container != container) { continue; } - for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { - auto itemMap_it = itemMap.find((*it)->getID()); - - uint8_t itemTier = Item::items[(*it)->getID()].upgradeClassification > 0 ? (*it)->getTier() + 1 : 0; - if (itemMap_it == itemMap.end()) { - std::map<uint8_t, uint32_t> itemTierMap; - itemTierMap[itemTier] = Item::countByType((*it), -1); - itemMap[(*it)->getID()] = itemTierMap; - count++; - } else if (auto itemTier_it = itemMap[(*it)->getID()].find(itemTier); itemTier_it == itemMap[(*it)->getID()].end()) { - itemMap[(*it)->getID()][itemTier] = Item::countByType((*it), -1); - count++; - } else { - itemMap[(*it)->getID()][itemTier] += Item::countByType((*it), -1); - } + if (slot < containerInfo.index) { + continue; } - } - for (const auto &[itemId, itemCount] : getStashItems()) { - auto itemMap_it = itemMap.find(itemId); - // Stackable items not have upgrade classification - if (Item::items[itemId].upgradeClassification > 0) { - g_logger().error("{} - Player {} have wrong item with id {} on stash with upgrade classification", __FUNCTION__, getName(), itemId); + const uint16_t pageEnd = containerInfo.index + container->capacity(); + if (slot >= pageEnd) { continue; } - if (itemMap_it == itemMap.end()) { - std::map<uint8_t, uint32_t> itemTierMap; - itemTierMap[0] = itemCount; - itemMap[itemId] = itemTierMap; - count++; - } else if (auto itemTier_it = itemMap[itemId].find(0); itemTier_it == itemMap[itemId].end()) { - itemMap[itemId][0] = itemCount; - count++; - } else { - itemMap[itemId][0] += itemCount; - } + client->sendUpdateContainerItem(containerId, slot, newItem); } - - setDepotSearchIsOpen(1, 0); - sendDepotItems(itemMap, count); } -void Player::requestDepotSearchItem(uint16_t itemId, uint8_t tier) { - ItemVector depotItems; - ItemVector inboxItems; - uint32_t depotCount = 0; - uint32_t inboxCount = 0; - uint32_t stashCount = 0; - - if (const ItemType &iType = Item::items[itemId]; - iType.stackable && iType.wareId > 0) { - stashCount = getStashItemCount(itemId); +void Player::sendRemoveContainerItem(const std::shared_ptr<Container> &container, uint16_t slot) { + if (!client) { + return; } - std::shared_ptr<DepotLocker> depotLocker = getDepotLocker(getLastDepotId()); - if (!depotLocker) { + if (!container) { return; } - for (const std::shared_ptr<Item> &locker : depotLocker->getItemList()) { - std::shared_ptr<Container> c = locker->getContainer(); - if (!c || c->empty()) { + for (auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container != container) { continue; } - for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; - if (!item || item->getID() != itemId || item->getTier() != tier) { - continue; - } - - if (c->isInbox()) { - if (inboxItems.size() < 255) { - inboxItems.push_back(item); - } - inboxCount += Item::countByType(item, -1); - } else { - if (depotItems.size() < 255) { - depotItems.push_back(item); - } - depotCount += Item::countByType(item, -1); - } + uint16_t &firstIndex = containerInfo.index; + if (firstIndex > 0 && firstIndex >= container->size() - 1) { + firstIndex -= container->capacity(); + sendContainer(containerId, container, false, firstIndex); } + + client->sendRemoveContainerItem(containerId, std::max<uint16_t>(slot, firstIndex), container->getItemByIndex(container->capacity() + firstIndex)); } +} - setDepotSearchIsOpen(itemId, tier); - sendDepotSearchResultDetail(itemId, tier, depotCount, depotItems, inboxCount, inboxItems, stashCount); +void Player::sendContainer(uint8_t cid, const std::shared_ptr<Container> &container, bool hasParent, uint16_t firstIndex) const { + if (client) { + client->sendContainer(cid, container, hasParent, firstIndex); + } } -void Player::retrieveAllItemsFromDepotSearch(uint16_t itemId, uint8_t tier, bool isDepot) { - std::shared_ptr<DepotLocker> depotLocker = getDepotLocker(getLastDepotId()); - if (!depotLocker) { - return; +// inventory + +void Player::sendDepotItems(const ItemsTierCountList &itemMap, uint16_t count) const { + if (client) { + client->sendDepotItems(itemMap, count); } +} - std::vector<std::shared_ptr<Item>> itemsVector; - for (const std::shared_ptr<Item> &locker : depotLocker->getItemList()) { - std::shared_ptr<Container> c = locker->getContainer(); - if (!c || c->empty() || - // Retrieve from inbox. - (c->isInbox() && isDepot) || - // Retrieve from depot. - (!c->isInbox() && !isDepot)) { - continue; - } +void Player::sendCloseDepotSearch() const { + if (client) { + client->sendCloseDepotSearch(); + } +} - for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; - if (!item) { - continue; - } +void Player::sendDepotSearchResultDetail(uint16_t itemId, uint8_t tier, uint32_t depotCount, const ItemVector &depotItems, uint32_t inboxCount, const ItemVector &inboxItems, uint32_t stashCount) const { + if (client) { + client->sendDepotSearchResultDetail(itemId, tier, depotCount, depotItems, inboxCount, inboxItems, stashCount); + } +} - if (item->getID() == itemId && item->getTier() == depotSearchOnItem.second) { - itemsVector.push_back(item); - } - } +void Player::sendCoinBalance() const { + if (client) { + client->sendCoinBalance(); + } +} + +void Player::sendInventoryItem(Slots_t slot, const std::shared_ptr<Item> &item) const { + if (client) { + client->sendInventoryItem(slot, item); } +} - ReturnValue ret = RETURNVALUE_NOERROR; - for (const std::shared_ptr<Item> &item : itemsVector) { - // First lets try to retrieve the item to the stash retrieve container. - if (g_game().tryRetrieveStashItems(static_self_cast<Player>(), item)) { +void Player::sendInventoryIds() const { + if (client) { + client->sendInventoryIds(); + } +} + +std::vector<std::shared_ptr<Condition>> Player::getMuteConditions() const { + std::vector<std::shared_ptr<Condition>> muteConditions; + muteConditions.reserve(conditions.size()); + + for (const auto &condition : conditions) { + if (condition->getTicks() <= 0) { continue; } - // If the retrieve fails to move the item to the stash retrieve container, let's add the item anywhere. - if (ret = g_game().internalMoveItem(item->getParent(), getPlayer(), INDEX_WHEREEVER, item, item->getItemCount(), nullptr); ret == RETURNVALUE_NOERROR) { + const auto &type = condition->getType(); + if (type != CONDITION_MUTED && type != CONDITION_CHANNELMUTEDTICKS && type != CONDITION_YELLTICKS) { continue; } - sendCancelMessage(ret); - return; + muteConditions.emplace_back(condition); } + return muteConditions; +} - requestDepotSearchItem(itemId, tier); +[[nodiscard]] std::shared_ptr<Guild> Player::getGuild() const { + return guild; } -void Player::openContainerFromDepotSearch(const Position &pos) { - if (!isDepotSearchOpen()) { - sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); +void Player::setGuild(const std::shared_ptr<Guild> &newGuild) { + if (newGuild == guild) { return; } - std::shared_ptr<Item> item = getItemFromDepotSearch(depotSearchOnItem.first, pos); - if (!item) { - sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; + if (guild) { + guild->removeMember(static_self_cast<Player>()); + guild = nullptr; } - std::shared_ptr<Container> container = item->getParent() ? item->getParent()->getContainer() : nullptr; - if (!container) { - sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; + guildNick.clear(); + guildRank = nullptr; + + if (newGuild) { + const auto &rank = newGuild->getRankByLevel(1); + if (!rank) { + return; + } + + guild = newGuild; + guildRank = rank; + newGuild->addMember(static_self_cast<Player>()); } +} - g_actions().useItem(static_self_cast<Player>(), pos, 0, container, false); +[[nodiscard]] GuildRank_ptr Player::getGuildRank() const { + return guildRank; } -std::shared_ptr<Item> Player::getItemFromDepotSearch(uint16_t itemId, const Position &pos) { - std::shared_ptr<DepotLocker> depotLocker = getDepotLocker(getLastDepotId()); - if (!depotLocker) { - return nullptr; +void Player::setGuildRank(GuildRank_ptr newGuildRank) { + guildRank = std::move(newGuildRank); +} + +bool Player::isGuildMate(const std::shared_ptr<Player> &player) const { + if (!player || !guild) { + return false; } + return guild == player->guild; +} - uint8_t index = 0; - for (const std::shared_ptr<Item> &locker : depotLocker->getItemList()) { - std::shared_ptr<Container> c = locker->getContainer(); - if (!c || c->empty() || (c->isInbox() && pos.y != 0x21) || // From inbox. - (!c->isInbox() && pos.y != 0x20)) { // From depot. - continue; - } +bool Player::addItemFromStash(uint16_t itemId, uint32_t itemCount) { + const uint32_t stackCount = 100u; - for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; - if (!item || item->getID() != itemId || item->getTier() != depotSearchOnItem.second) { - continue; - } + while (itemCount > 0) { + const auto addValue = itemCount > stackCount ? stackCount : itemCount; + itemCount -= addValue; + const auto &newItem = Item::CreateItem(itemId, addValue); - if (pos.z == index) { - return item; - } - index++; + if (!g_game().tryRetrieveStashItems(static_self_cast<Player>(), newItem)) { + g_game().internalPlayerAddItem(static_self_cast<Player>(), newItem, true); } } - return nullptr; + // This check is necessary because we need to block it when we retrieve an item from depot search. + if (!isDepotSearchOpenOnItem(itemId)) { + sendOpenStash(); + } + + return true; } -std::pair<std::vector<std::shared_ptr<Item>>, std::map<uint16_t, std::map<uint8_t, uint32_t>>> -Player::requestLockerItems(std::shared_ptr<DepotLocker> depotLocker, bool sendToClient /*= false*/, uint8_t tier /*= 0*/) const { - if (!depotLocker) { - g_logger().error("{} - Depot locker is nullptr", __FUNCTION__); - return {}; +void sendStowItems(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &stowItem, StashContainerList &itemDict) { + if (stowItem->getID() == item->getID()) { + itemDict.emplace_back(stowItem, stowItem->getItemCount()); } - std::map<uint16_t, std::map<uint8_t, uint32_t>> lockerItems; - std::vector<std::shared_ptr<Item>> itemVector; - std::vector<std::shared_ptr<Container>> containers { depotLocker }; + if (const auto &container = stowItem->getContainer()) { + std::ranges::copy_if(container->getStowableItems(), std::back_inserter(itemDict), [&item](const auto &stowable_it) { + return stowable_it.first->getID() == item->getID(); + }); + } +} - for (size_t i = 0; i < containers.size(); ++i) { - std::shared_ptr<Container> container = containers[i]; +void Player::stowItem(const std::shared_ptr<Item> &item, uint32_t count, bool allItems) { + if (!item || (!item->isItemStorable() && item->getID() != ITEM_GOLD_POUCH)) { + sendCancelMessage("This item cannot be stowed here."); + return; + } - for (const auto &item : container->getItemList()) { - std::shared_ptr<Container> lockerContainers = item->getContainer(); - if (lockerContainers && !lockerContainers->empty()) { - containers.push_back(lockerContainers); - continue; + StashContainerList itemDict; + if (allItems) { + if (!item->isInsideDepot(true)) { + // Stow "all items" from player backpack + if (const auto &backpack = getInventoryItem(CONST_SLOT_BACKPACK)) { + sendStowItems(item, backpack, itemDict); } - const ItemType &itemType = Item::items[item->getID()]; - if (item->isStoreItem() || itemType.wareId == 0) { - continue; + // Stow "all items" from loot pouch + const auto &itemParent = item->getParent(); + const auto &lootPouch = itemParent->getItem(); + if (itemParent && lootPouch && lootPouch->getID() == ITEM_GOLD_POUCH) { + sendStowItems(item, lootPouch, itemDict); } + } - if (lockerContainers && (!itemType.isContainer() || lockerContainers->capacity() != itemType.maxItems)) { - continue; + // Stow locker items + const auto &depotLocker = getDepotLocker(getLastDepotId()); + const auto &[itemVector, itemMap] = requestLockerItems(depotLocker); + for (const auto &lockerItem : itemVector) { + if (lockerItem == nullptr) { + break; } - if (!item->hasMarketAttributes() || (!sendToClient && item->getTier() != tier)) { - continue; + if (item->isInsideDepot(true)) { + sendStowItems(item, lockerItem, itemDict); + } + } + } else if (item->getContainer()) { + itemDict = item->getContainer()->getStowableItems(); + for (const std::shared_ptr<Item> &containerItem : item->getContainer()->getItems(true)) { + uint32_t depotChest = g_configManager().getNumber(DEPOTCHEST); + bool validDepot = depotChest > 0 && depotChest < 21; + if (g_configManager().getBoolean(STASH_MOVING) && containerItem && !containerItem->isStackable() && validDepot) { + g_game().internalMoveItem(containerItem->getParent(), getDepotChest(depotChest, true), INDEX_WHEREEVER, containerItem, containerItem->getItemCount(), nullptr); + movedItems++; + moved = true; } - - lockerItems[itemType.wareId][item->getTier()] += Item::countByType(item, -1); - itemVector.push_back(item); } + } else { + itemDict.emplace_back(item, count); } - StashItemList stashToSend = getStashItems(); - for (const auto &[itemId, itemCount] : stashToSend) { - const ItemType &itemType = Item::items[itemId]; - if (itemType.wareId != 0) { - lockerItems[itemType.wareId][0] += itemCount; - } + if (itemDict.empty()) { + sendCancelMessage("There is no stowable items on this container."); + return; } - return { itemVector, lockerItems }; + stashContainer(itemDict); } -std::pair<std::vector<std::shared_ptr<Item>>, uint16_t> Player::getLockerItemsAndCountById(const std::shared_ptr<DepotLocker> &depotLocker, uint8_t tier, uint16_t itemId) { - std::vector<std::shared_ptr<Item>> lockerItems; - auto [itemVector, itemMap] = requestLockerItems(depotLocker, false, tier); - uint16_t totalCount = 0; - for (const auto &item : itemVector) { - if (!item || item->getID() != itemId) { - continue; +void Player::sendPreyData() const { + if (client) { + for (const std::unique_ptr<PreySlot> &slot : preys) { + client->sendPreyData(slot); } - totalCount++; - lockerItems.push_back(item); + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards()); } +} - return std::make_pair(lockerItems, totalCount); +void Player::sendPreyTimeLeft(const std::unique_ptr<PreySlot> &slot) const { + if (g_configManager().getBoolean(PREY_ENABLED) && client) { + client->sendPreyTimeLeft(slot); + } } -bool Player::saySpell( - SpeakClasses type, - const std::string &text, - bool ghostMode, - Spectators* spectatorsPtr /* = nullptr*/, - const Position* pos /* = nullptr*/ -) { - if (text.empty()) { - g_logger().debug("{} - Spell text is empty for player {}", __FUNCTION__, getName()); +void Player::reloadPreySlot(PreySlot_t slotid) { + if (g_configManager().getBoolean(PREY_ENABLED) && client) { + client->sendPreyData(getPreySlotById(slotid)); + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); + } +} + +const std::unique_ptr<PreySlot> &Player::getPreySlotById(PreySlot_t slotid) { + if (auto it = std::ranges::find_if(preys, [slotid](const std::unique_ptr<PreySlot> &preyIt) { + return preyIt->id == slotid; + }); + it != preys.end()) { + return *it; + } + + return PreySlotNull; +} + +bool Player::setPreySlotClass(std::unique_ptr<PreySlot> &slot) { + if (getPreySlotById(slot->id)) { return false; } - if (!pos) { - pos = &getPosition(); + preys.emplace_back(std::move(slot)); + return true; +} + +bool Player::usePreyCards(uint16_t amount) { + if (preyCards < amount) { + return false; } - Spectators spectators; + preyCards -= amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); + } + return true; +} - if (!spectatorsPtr || spectatorsPtr->empty()) { - // This somewhat complex construct ensures that the cached Spectators - // is used if available and if it can be used, else a local vector is - // used (hopefully the compiler will optimize away the construction of - // the temporary when it's not used). - if (type != TALKTYPE_YELL && type != TALKTYPE_MONSTER_YELL) { - spectators.find<Creature>(*pos, false, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_Y, MAP_MAX_CLIENT_VIEW_PORT_Y); - } else { - spectators.find<Creature>(*pos, true, (MAP_MAX_CLIENT_VIEW_PORT_X + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_X + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_Y + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_Y + 1) * 2); - } - } else { - spectators = (*spectatorsPtr); +void Player::addPreyCards(uint64_t amount) { + preyCards += amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); } +} - int32_t valueEmote = 0; - // Send to client - for (const std::shared_ptr<Creature> &spectator : spectators) { - if (std::shared_ptr<Player> tmpPlayer = spectator->getPlayer()) { - if (g_configManager().getBoolean(EMOTE_SPELLS)) { - valueEmote = tmpPlayer->getStorageValue(STORAGEVALUE_EMOTE); +uint64_t Player::getPreyCards() const { + return preyCards; +} + +uint32_t Player::getPreyRerollPrice() const { + return getLevel() * g_configManager().getNumber(PREY_REROLL_PRICE_LEVEL); +} + +std::vector<uint16_t> Player::getPreyBlackList() const { + std::vector<uint16_t> rt; + for (const std::unique_ptr<PreySlot> &slot : preys) { + if (slot) { + if (slot->isOccupied()) { + rt.push_back(slot->selectedRaceId); } - if (!ghostMode || tmpPlayer->canSeeCreature(static_self_cast<Player>())) { - if (valueEmote == 1) { - tmpPlayer->sendCreatureSay(static_self_cast<Player>(), TALKTYPE_MONSTER_SAY, text, pos); - } else { - tmpPlayer->sendCreatureSay(static_self_cast<Player>(), TALKTYPE_SPELL_USE, text, pos); - } + for (uint16_t raceId : slot->raceIdList) { + rt.push_back(raceId); } } } - // Execute lua event method - for (const std::shared_ptr<Creature> &spectator : spectators) { - auto tmpPlayer = spectator->getPlayer(); - if (!tmpPlayer) { - continue; - } + return rt; +} - tmpPlayer->onCreatureSay(static_self_cast<Player>(), type, text); - if (static_self_cast<Player>() != tmpPlayer) { - g_events().eventCreatureOnHear(tmpPlayer, getPlayer(), text, type); - g_callbacks().executeCallback(EventCallback_t::creatureOnHear, &EventCallback::creatureOnHear, tmpPlayer, getPlayer(), text, type); - } +const std::unique_ptr<PreySlot> &Player::getPreyWithMonster(uint16_t raceId) const { + if (!g_configManager().getBoolean(PREY_ENABLED)) { + return PreySlotNull; } - return true; + + if (auto it = std::ranges::find_if(preys, [raceId](const std::unique_ptr<PreySlot> &preyPtr) { + return preyPtr->selectedRaceId == raceId; + }); + it != preys.end()) { + return *it; + } + + return PreySlotNull; } -// Forge system -void Player::forgeFuseItems(ForgeAction_t actionType, uint16_t firstItemId, uint8_t tier, uint16_t secondItemId, bool success, bool reduceTierLoss, bool convergence, uint8_t bonus, uint8_t coreCount) { - if (getFreeBackpackSlots() == 0) { - sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - return; +// Task hunting system + +void Player::initializeTaskHunting() { + if (taskHunting.empty()) { + for (uint8_t slotId = PreySlot_First; slotId <= PreySlot_Last; slotId++) { + auto slot = std::make_unique<TaskHuntingSlot>(static_cast<PreySlot_t>(slotId)); + if (!g_configManager().getBoolean(TASK_HUNTING_ENABLED)) { + slot->state = PreyTaskDataState_Inactive; + } else if (slot->id == PreySlot_Three && !g_configManager().getBoolean(TASK_HUNTING_FREE_THIRD_SLOT)) { + slot->state = PreyTaskDataState_Locked; + } else if (slot->id == PreySlot_Two && !isPremium()) { + slot->state = PreyTaskDataState_Locked; + } else { + slot->state = PreyTaskDataState_Selection; + slot->reloadMonsterGrid(getTaskHuntingBlackList(), getLevel()); + } + + setTaskHuntingSlotClass(slot); + } } - ForgeHistory history; - history.actionType = actionType; - history.tier = tier; - history.success = success; - history.tierLoss = reduceTierLoss; + if (client && g_configManager().getBoolean(TASK_HUNTING_ENABLED) && !client->oldProtocol) { + client->writeToOutputBuffer(g_ioprey().getTaskHuntingBaseDate()); + } +} - auto firstForgingItem = getForgeItemFromId(firstItemId, tier); - if (!firstForgingItem) { - g_logger().error("[Log 1] Player with name {} failed to fuse item with id {}", getName(), firstItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; +bool Player::isCreatureUnlockedOnTaskHunting(const std::shared_ptr<MonsterType> &mtype) const { + if (!mtype) { + return false; } - auto returnValue = g_game().internalRemoveItem(firstForgingItem, 1); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 1] Failed to remove forge item {} from player with name {}", firstItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + + return getBestiaryKillCount(mtype->info.raceid) >= mtype->info.bestiaryToUnlock; +} + +bool Player::setTaskHuntingSlotClass(std::unique_ptr<TaskHuntingSlot> &slot) { + if (getTaskHuntingSlotById(slot->id)) { + return false; } - auto secondForgingItem = getForgeItemFromId(secondItemId, tier); - if (!secondForgingItem) { - g_logger().error("[Log 2] Player with name {} failed to fuse item with id {}", getName(), secondItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + + taskHunting.emplace_back(std::move(slot)); + return true; +} + +uint8_t Player::getBlessingCount(uint8_t index, bool storeCount) const { + if (!storeCount) { + if (index > 0 && index <= blessings.size()) { + return blessings[index - 1]; + } else { + g_logger().error("[{}] - index outside range 0-10.", __FUNCTION__); + return 0; + } } - if (returnValue = g_game().internalRemoveItem(secondForgingItem, 1); - returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 2] Failed to remove forge item {} from player with name {}", secondItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + auto amount = kv()->scoped("summary")->scoped("blessings")->scoped(fmt::format("{}", index))->get("amount"); + return amount ? static_cast<uint8_t>(amount->getNumber()) : 0; +} + +std::string Player::getBlessingsName() const { + std::vector<std::string> blessingNames; + for (const auto &bless : magic_enum::enum_values<Blessings>()) { + if (hasBlessing(enumToValue(bless))) { + std::string name = toStartCaseWithSpace(magic_enum::enum_name(bless).data()); + blessingNames.emplace_back(name); + } } - auto exaltationChest = Item::CreateItem(ITEM_EXALTATION_CHEST, 1); - if (!exaltationChest) { - g_logger().error("Failed to create exaltation chest"); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + std::ostringstream os; + if (!blessingNames.empty()) { + // Join all elements but the last with ", " and add the last one with " and " + for (size_t i = 0; i < blessingNames.size() - 1; ++i) { + os << blessingNames[i] << ", "; + } + if (blessingNames.size() > 1) { + os << "and "; + } + os << blessingNames.back() << "."; } - auto exaltationContainer = exaltationChest->getContainer(); - if (!exaltationContainer) { - g_logger().error("Failed to create exaltation container"); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + + return os.str(); +} + +void Player::disconnect() const { + if (client) { + client->disconnect(); } +} - std::shared_ptr<Item> firstForgedItem = Item::CreateItem(firstItemId, 1); - if (!firstForgedItem) { - g_logger().error("[Log 3] Player with name {} failed to fuse item with id {}", getName(), firstItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; +uint32_t Player::getIP() const { + return client ? client->getIP() : 0; +} + +void Player::reloadTaskSlot(PreySlot_t slotid) { + if (g_configManager().getBoolean(TASK_HUNTING_ENABLED) && client) { + client->sendTaskHuntingData(getTaskHuntingSlotById(slotid)); + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); } - returnValue = g_game().internalAddItem(exaltationContainer, firstForgedItem, INDEX_WHEREEVER); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 1] Failed to add forge item {} from player with name {}", firstItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; +} + +const std::unique_ptr<TaskHuntingSlot> &Player::getTaskHuntingSlotById(PreySlot_t slotid) { + if (auto it = std::ranges::find_if(taskHunting, [slotid](const std::unique_ptr<TaskHuntingSlot> &itTask) { + return itTask->id == slotid; + }); + it != taskHunting.end()) { + return *it; } - auto configKey = convergence ? FORGE_CONVERGENCE_FUSION_DUST_COST : FORGE_FUSION_DUST_COST; - auto dustCost = static_cast<uint64_t>(g_configManager().getNumber(configKey)); - if (convergence) { - firstForgedItem->setTier(tier + 1); - history.dustCost = dustCost; - setForgeDusts(getForgeDusts() - dustCost); + return TaskHuntingSlotNull; +} - uint64_t cost = 0; - for (const auto* itemClassification : g_game().getItemsClassifications()) { - if (itemClassification->id != firstForgingItem->getClassification()) { - continue; - } +std::vector<uint16_t> Player::getTaskHuntingBlackList() const { + std::vector<uint16_t> rt; - for (const auto &[mapTier, mapPrice] : itemClassification->tiers) { - if (mapTier == firstForgingItem->getTier() + 1) { - cost = mapPrice.convergenceFusionPrice; - break; - } - } - break; - } - if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { - g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_convergence_fuse" } }); - history.cost = cost; - } else { - firstForgedItem->setTier(tier); - std::shared_ptr<Item> secondForgedItem = Item::CreateItem(secondItemId, 1); - if (!secondForgedItem) { - g_logger().error("[Log 4] Player with name {} failed to fuse item with id {}", getName(), secondItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + std::ranges::for_each(taskHunting, [&rt](const std::unique_ptr<TaskHuntingSlot> &slot) { + if (slot->isOccupied()) { + rt.push_back(slot->selectedRaceId); + } else { + std::ranges::for_each(slot->raceIdList, [&rt](uint16_t raceId) { + rt.push_back(raceId); + }); } + }); - secondForgedItem->setTier(tier); - returnValue = g_game().internalAddItem(exaltationContainer, secondForgedItem, INDEX_WHEREEVER); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 2] Failed to add forge item {} from player with name {}", secondItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + return rt; +} + +void Player::sendTaskHuntingData() const { + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); + for (const std::unique_ptr<TaskHuntingSlot> &slot : taskHunting) { + if (slot) { + client->sendTaskHuntingData(slot); + } } + } +} - if (success) { - firstForgedItem->setTier(tier + 1); +void Player::addTaskHuntingPoints(uint64_t amount) { + taskHuntingPoints += amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); + } +} - if (bonus != 1) { - history.dustCost = dustCost; - setForgeDusts(getForgeDusts() - dustCost); - } - if (bonus != 2) { - if (coreCount != 0 && !removeItemCountById(ITEM_FORGE_CORE, coreCount)) { - g_logger().error("[{}][Log 1] Failed to remove item 'id :{} count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), coreCount, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - history.coresCost = coreCount; - } - if (bonus != 3) { - uint64_t cost = 0; - for (const auto* itemClassification : g_game().getItemsClassifications()) { - if (itemClassification->id != firstForgedItem->getClassification()) { - continue; - } - if (!itemClassification->tiers.contains(firstForgedItem->getTier())) { - g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, firstForgedItem->getTier(), firstForgedItem->getClassification(), itemClassification->id); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - break; - } - cost = itemClassification->tiers.at(firstForgedItem->getTier()).regularPrice; - break; - } - if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { - g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_fuse" } }); - history.cost = cost; - } - - if (bonus == 4) { - if (tier > 0) { - secondForgedItem->setTier(tier - 1); - } - } else if (bonus == 6) { - secondForgedItem->setTier(tier + 1); - } else if (bonus == 7 && tier + 2 <= firstForgedItem->getClassification()) { - firstForgedItem->setTier(tier + 2); - } - - if (bonus != 4 && bonus != 5 && bonus != 6 && bonus != 8) { - returnValue = g_game().internalRemoveItem(secondForgedItem, 1); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 6] Failed to remove forge item {} from player with name {}", secondItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - } - } else { - auto isTierLost = uniform_random(1, 100) <= (reduceTierLoss ? g_configManager().getNumber(FORGE_TIER_LOSS_REDUCTION) : 100); - if (isTierLost) { - if (secondForgedItem->getTier() >= 1) { - secondForgedItem->setTier(tier - 1); - } else { - returnValue = g_game().internalRemoveItem(secondForgedItem, 1); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 7] Failed to remove forge item {} from player with name {}", secondItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - } - } - bonus = (isTierLost ? 0 : 8); - history.coresCost = coreCount; +bool Player::useTaskHuntingPoints(uint64_t amount) { + if (taskHuntingPoints < amount) { + return false; + } - if (getForgeDusts() < dustCost) { - g_logger().error("[Log 7] Failed to remove fuse dusts from player with name {}", getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } else { - setForgeDusts(getForgeDusts() - dustCost); - } + taskHuntingPoints -= amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); + } + return true; +} - if (coreCount != 0 && !removeItemCountById(ITEM_FORGE_CORE, coreCount)) { - g_logger().error("[{}][Log 2] Failed to remove item 'id: {}, count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), coreCount, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } +uint64_t Player::getTaskHuntingPoints() const { + return taskHuntingPoints; +} - uint64_t cost = 0; - for (const auto* itemClassification : g_game().getItemsClassifications()) { - if (itemClassification->id != firstForgingItem->getClassification()) { - continue; - } - if (!itemClassification->tiers.contains(firstForgingItem->getTier() + 1)) { - g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, firstForgingItem->getTier() + 1, firstForgingItem->getClassification(), itemClassification->id); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - break; - } - cost = itemClassification->tiers.at(firstForgingItem->getTier() + 1).regularPrice; - break; - } - if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { - g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_fuse" } }); +uint32_t Player::getTaskHuntingRerollPrice() const { + return getLevel() * g_configManager().getNumber(TASK_HUNTING_REROLL_PRICE_LEVEL); +} - history.cost = cost; - } +const std::unique_ptr<TaskHuntingSlot> &Player::getTaskHuntingWithCreature(uint16_t raceId) const { + if (!g_configManager().getBoolean(TASK_HUNTING_ENABLED)) { + return TaskHuntingSlotNull; } - returnValue = g_game().internalAddItem(static_self_cast<Player>(), exaltationContainer, INDEX_WHEREEVER); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("Failed to add exaltation chest to player with name {}", fmt::underlying(ITEM_EXALTATION_CHEST), getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + if (auto it = std::ranges::find_if(taskHunting, [raceId](const std::unique_ptr<TaskHuntingSlot> &itTask) { + return itTask->selectedRaceId == raceId; + }); + it != taskHunting.end()) { + return *it; } - history.firstItemName = firstForgingItem->getName(); - history.secondItemName = secondForgingItem->getName(); - history.bonus = bonus; - history.createdAt = getTimeNow(); - history.convergence = convergence; - registerForgeHistoryDescription(history); + return TaskHuntingSlotNull; +} - sendForgeResult(actionType, firstItemId, tier, secondItemId, tier + 1, success, bonus, coreCount, convergence); +uint32_t Player::getLoyaltyPoints() const { + return loyaltyPoints; } -void Player::forgeTransferItemTier(ForgeAction_t actionType, uint16_t donorItemId, uint8_t tier, uint16_t receiveItemId, bool convergence) { - if (getFreeBackpackSlots() == 0) { - sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - return; - } +void Player::setLoyaltyBonus(uint16_t bonus) { + loyaltyBonusPercent = bonus; + sendSkills(); +} - ForgeHistory history; - history.actionType = actionType; - history.tier = tier; - history.success = true; +void Player::setLoyaltyTitle(std::string title) { + loyaltyTitle = std::move(title); +} - auto donorItem = getForgeItemFromId(donorItemId, tier); - if (!donorItem) { - g_logger().error("[Log 1] Player with name {} failed to transfer item with id {}", getName(), donorItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - auto returnValue = g_game().internalRemoveItem(donorItem, 1); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 1] Failed to remove transfer item {} from player with name {}", donorItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } +std::string Player::getLoyaltyTitle() const { + return loyaltyTitle; +} - auto receiveItem = getForgeItemFromId(receiveItemId, 0); - if (!receiveItem) { - g_logger().error("[Log 2] Player with name {} failed to transfer item with id {}", getName(), receiveItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - if (returnValue = g_game().internalRemoveItem(receiveItem, 1); - returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 2] Failed to remove transfer item {} from player with name {}", receiveItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } +uint16_t Player::getLoyaltyBonus() const { + return loyaltyBonusPercent; +} - auto exaltationChest = Item::CreateItem(ITEM_EXALTATION_CHEST, 1); - if (!exaltationChest) { - g_logger().error("Exaltation chest is nullptr"); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } - auto exaltationContainer = exaltationChest->getContainer(); - if (!exaltationContainer) { - g_logger().error("Exaltation container is nullptr"); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } +// Depot search system +/******************************************************************************* + * Depot search system + ******************************************************************************/ - std::shared_ptr<Item> newReceiveItem = Item::CreateItem(receiveItemId, 1); - if (!newReceiveItem) { - g_logger().error("[Log 6] Player with name {} failed to fuse item with id {}", getName(), receiveItemId); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); +void Player::requestDepotItems() { + ItemsTierCountList itemMap; + uint16_t count = 0; + const auto &depotLocker = getDepotLocker(getLastDepotId()); + if (!depotLocker) { return; } - auto configKey = convergence ? FORGE_CONVERGENCE_TRANSFER_DUST_COST : FORGE_TRANSFER_DUST_COST; - if (getForgeDusts() < g_configManager().getNumber(configKey)) { - g_logger().error("[Log 8] Failed to remove transfer dusts from player with name {}", getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } else { - setForgeDusts(getForgeDusts() - g_configManager().getNumber(configKey)); - } + for (const auto &locker : depotLocker->getItemList()) { + const auto &c = locker->getContainer(); + if (!c || c->empty()) { + continue; + } - if (convergence) { - newReceiveItem->setTier(tier); - } else { - newReceiveItem->setTier(tier - 1); - } - returnValue = g_game().internalAddItem(exaltationContainer, newReceiveItem, INDEX_WHEREEVER); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 7] Failed to add forge item {} from player with name {}", receiveItemId, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { + auto itemMap_it = itemMap.find((*it)->getID()); + + uint8_t itemTier = Item::items[(*it)->getID()].upgradeClassification > 0 ? (*it)->getTier() + 1 : 0; + if (itemMap_it == itemMap.end()) { + std::map<uint8_t, uint32_t> itemTierMap; + itemTierMap[itemTier] = Item::countByType((*it), -1); + itemMap[(*it)->getID()] = itemTierMap; + count++; + } else if (auto itemTier_it = itemMap[(*it)->getID()].find(itemTier); itemTier_it == itemMap[(*it)->getID()].end()) { + itemMap[(*it)->getID()][itemTier] = Item::countByType((*it), -1); + count++; + } else { + itemMap[(*it)->getID()][itemTier] += Item::countByType((*it), -1); + } + } } - uint8_t coresAmount = 0; - uint64_t cost = 0; - for (const auto &itemClassification : g_game().getItemsClassifications()) { - if (itemClassification->id != donorItem->getClassification()) { + for (const auto &[itemId, itemCount] : getStashItems()) { + auto itemMap_it = itemMap.find(itemId); + // Stackable items not have upgrade classification + if (Item::items[itemId].upgradeClassification > 0) { + g_logger().error("{} - Player {} have wrong item with id {} on stash with upgrade classification", __FUNCTION__, getName(), itemId); continue; } - if (!itemClassification->tiers.contains(donorItem->getTier())) { - g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, donorItem->getTier(), donorItem->getClassification(), itemClassification->id); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - break; - } - const uint8_t toTier = convergence ? donorItem->getTier() : donorItem->getTier() - 1; - auto tierPriecs = itemClassification->tiers.at(toTier); - cost = convergence ? tierPriecs.convergenceTransferPrice : tierPriecs.regularPrice; - coresAmount = tierPriecs.corePrice; - break; + if (itemMap_it == itemMap.end()) { + std::map<uint8_t, uint32_t> itemTierMap; + itemTierMap[0] = itemCount; + itemMap[itemId] = itemTierMap; + count++; + } else if (auto itemTier_it = itemMap[itemId].find(0); itemTier_it == itemMap[itemId].end()) { + itemMap[itemId][0] = itemCount; + count++; + } else { + itemMap[itemId][0] += itemCount; + } } - if (!removeItemCountById(ITEM_FORGE_CORE, coresAmount)) { - g_logger().error("[{}] Failed to remove item 'id: {}, count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), 1, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; - } + setDepotSearchIsOpen(1, 0); + sendDepotItems(itemMap, count); +} - if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { - g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; +void Player::requestDepotSearchItem(uint16_t itemId, uint8_t tier) { + ItemVector depotItems; + ItemVector inboxItems; + uint32_t depotCount = 0; + uint32_t inboxCount = 0; + uint32_t stashCount = 0; + + if (const ItemType &iType = Item::items[itemId]; + iType.stackable && iType.wareId > 0) { + stashCount = getStashItemCount(itemId); } - history.cost = cost; - g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_transfer" } }); - returnValue = g_game().internalAddItem(static_self_cast<Player>(), exaltationContainer, INDEX_WHEREEVER); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("[Log 10] Failed to add forge item {} from player with name {}", fmt::underlying(ITEM_EXALTATION_CHEST), getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + const auto &depotLocker = getDepotLocker(getLastDepotId()); + if (!depotLocker) { return; } - history.firstItemName = Item::items[donorItemId].name; - history.secondItemName = newReceiveItem->getName(); - history.createdAt = getTimeNow(); - history.convergence = convergence; - registerForgeHistoryDescription(history); + for (const auto &locker : depotLocker->getItemList()) { + const auto &c = locker->getContainer(); + if (!c || c->empty()) { + continue; + } - sendForgeResult(actionType, donorItemId, tier, receiveItemId, convergence ? tier : tier - 1, true, 0, 0, convergence); + inboxItems.reserve(inboxItems.size()); + depotItems.reserve(depotItems.size()); + + for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { + const auto item = *it; + if (!item || item->getID() != itemId || item->getTier() != tier) { + continue; + } + + if (c->isInbox()) { + if (inboxItems.size() < 255) { + inboxItems.emplace_back(item); + } + inboxCount += Item::countByType(item, -1); + } else { + if (depotItems.size() < 255) { + depotItems.emplace_back(item); + } + depotCount += Item::countByType(item, -1); + } + } + } + + setDepotSearchIsOpen(itemId, tier); + sendDepotSearchResultDetail(itemId, tier, depotCount, depotItems, inboxCount, inboxItems, stashCount); } -void Player::forgeResourceConversion(ForgeAction_t actionType) { - ForgeHistory history; - history.actionType = actionType; - history.success = true; +void Player::retrieveAllItemsFromDepotSearch(uint16_t itemId, uint8_t tier, bool isDepot) { + const auto &depotLocker = getDepotLocker(getLastDepotId()); + if (!depotLocker) { + return; + } - ReturnValue returnValue = RETURNVALUE_NOERROR; - if (actionType == ForgeAction_t::DUSTTOSLIVERS) { - auto dusts = getForgeDusts(); - auto cost = static_cast<uint16_t>(g_configManager().getNumber(FORGE_COST_ONE_SLIVER) * g_configManager().getNumber(FORGE_SLIVER_AMOUNT)); - if (cost > dusts) { - g_logger().error("[{}] Not enough dust", __FUNCTION__); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + std::vector<std::shared_ptr<Item>> itemsVector; + for (const auto &locker : depotLocker->getItemList()) { + const auto &c = locker->getContainer(); + if (!c || c->empty() || + // Retrieve from inbox. + (c->isInbox() && isDepot) || + // Retrieve from depot. + (!c->isInbox() && !isDepot)) { + continue; } - auto itemCount = static_cast<uint16_t>(g_configManager().getNumber(FORGE_SLIVER_AMOUNT)); - std::shared_ptr<Item> item = Item::CreateItem(ITEM_FORGE_SLIVER, itemCount); - returnValue = g_game().internalPlayerAddItem(static_self_cast<Player>(), item); - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("Failed to add {} slivers to player with name {}", itemCount, getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { + const auto &item = *it; + if (!item) { + continue; + } + + if (item->getID() == itemId && item->getTier() == depotSearchOnItem.second) { + itemsVector.emplace_back(item); + } } - history.cost = cost; - history.gained = 3; - setForgeDusts(dusts - cost); - } else if (actionType == ForgeAction_t::SLIVERSTOCORES) { - auto [sliverCount, coreCount] = getForgeSliversAndCores(); - auto cost = static_cast<uint16_t>(g_configManager().getNumber(FORGE_CORE_COST)); - if (cost > sliverCount) { - g_logger().error("[{}] Not enough sliver", __FUNCTION__); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + } + + ReturnValue ret = RETURNVALUE_NOERROR; + for (const auto &item : itemsVector) { + if (!item) { + continue; } - if (!removeItemCountById(ITEM_FORGE_SLIVER, cost)) { - g_logger().error("[{}] Failed to remove item 'id: {}, count {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_SLIVER), cost, getName()); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + // First lets try to retrieve the item to the stash retrieve container. + if (g_game().tryRetrieveStashItems(static_self_cast<Player>(), item)) { + continue; } - if (std::shared_ptr<Item> item = Item::CreateItem(ITEM_FORGE_CORE, 1); - item) { - returnValue = g_game().internalPlayerAddItem(static_self_cast<Player>(), item); + // If the retrieve fails to move the item to the stash retrieve container, let's add the item anywhere. + if (ret = g_game().internalMoveItem(item->getParent(), getPlayer(), INDEX_WHEREEVER, item, item->getItemCount(), nullptr); ret == RETURNVALUE_NOERROR) { + continue; } - if (returnValue != RETURNVALUE_NOERROR) { - g_logger().error("Failed to add one core to player with name {}", getName()); - sendCancelMessage(getReturnMessage(returnValue)); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + + sendCancelMessage(ret); + return; + } + + requestDepotSearchItem(itemId, tier); +} + +void Player::openContainerFromDepotSearch(const Position &pos) { + if (!isDepotSearchOpen()) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + + const auto &item = getItemFromDepotSearch(depotSearchOnItem.first, pos); + if (!item) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + + const auto &container = item->getParent() ? item->getParent()->getContainer() : nullptr; + if (!container) { + sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + + g_actions().useItem(static_self_cast<Player>(), pos, 0, container, false); +} + +std::shared_ptr<Item> Player::getItemFromDepotSearch(uint16_t itemId, const Position &pos) { + const auto &depotLocker = getDepotLocker(getLastDepotId()); + if (!depotLocker) { + return nullptr; + } + + uint8_t index = 0; + for (const auto &locker : depotLocker->getItemList()) { + const auto &c = locker->getContainer(); + if (!c || c->empty() || (c->isInbox() && pos.y != 0x21) || // From inbox. + (!c->isInbox() && pos.y != 0x20)) { // From depot. + continue; } - history.cost = cost; - history.gained = 1; - } else { - auto dustLevel = getForgeDustLevel(); - if (dustLevel >= g_configManager().getNumber(FORGE_MAX_DUST)) { - g_logger().error("[{}] Maximum level reached", __FUNCTION__); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + for (ContainerIterator it = c->iterator(); it.hasNext(); it.advance()) { + const auto &item = *it; + if (!item || item->getID() != itemId || item->getTier() != depotSearchOnItem.second) { + continue; + } + + if (pos.z == index) { + return item; + } + index++; } + } - auto upgradeCost = dustLevel - 75; - if (auto dusts = getForgeDusts(); - upgradeCost > dusts) { - g_logger().error("[{}] Not enough dust", __FUNCTION__); - sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); - return; + return nullptr; +} + +std::pair<std::vector<std::shared_ptr<Item>>, std::map<uint16_t, std::map<uint8_t, uint32_t>>> Player::requestLockerItems(const std::shared_ptr<DepotLocker> &depotLocker, bool sendToClient, uint8_t tier) const { + if (!depotLocker) { + g_logger().error("{} - Depot locker is nullptr", __FUNCTION__); + return {}; + } + + std::map<uint16_t, std::map<uint8_t, uint32_t>> lockerItems; + std::vector<std::shared_ptr<Item>> itemVector; + std::vector<std::shared_ptr<Container>> containers { depotLocker }; + + for (size_t i = 0; i < containers.size(); ++i) { + const auto &container = containers[i]; + + for (const auto &item : container->getItemList()) { + const auto &lockerContainers = item->getContainer(); + if (lockerContainers && !lockerContainers->empty()) { + containers.emplace_back(lockerContainers); + continue; + } + + const ItemType &itemType = Item::items[item->getID()]; + if (item->isStoreItem() || itemType.wareId == 0) { + continue; + } + + if (lockerContainers && (!itemType.isContainer() || lockerContainers->capacity() != itemType.maxItems)) { + continue; + } + + if (!item->hasMarketAttributes() || (!sendToClient && item->getTier() != tier)) { + continue; + } + + lockerItems[itemType.wareId][item->getTier()] += Item::countByType(item, -1); + itemVector.emplace_back(item); } + } - history.cost = upgradeCost; - history.gained = dustLevel; - removeForgeDusts(upgradeCost); - addForgeDustLevel(1); + StashItemList stashToSend = getStashItems(); + for (const auto &[itemId, itemCount] : stashToSend) { + const ItemType &itemType = Item::items[itemId]; + if (itemType.wareId != 0) { + lockerItems[itemType.wareId][0] += itemCount; + } } - history.createdAt = getTimeNow(); - registerForgeHistoryDescription(history); - sendForgingData(); + return { itemVector, lockerItems }; } -void Player::forgeHistory(uint8_t page) const { - sendForgeHistory(page); +/** + This function returns a pair of an array of items and a 16-bit integer from a DepotLocker instance, a 8-bit byte and a 16-bit integer. + @param depotLocker The instance of DepotLocker from which to retrieve items. + @param tier The 8-bit byte that specifies the level of the tier to search. + @param itemId The 16-bit integer that specifies the ID of the item to search for. + @return A pair of an array of items and a 16-bit integer, where the array of items is filled with all items from the + locker with the specified id and the 16-bit integer is the total items found. + */ + +std::pair<std::vector<std::shared_ptr<Item>>, uint16_t> Player::getLockerItemsAndCountById(const std::shared_ptr<DepotLocker> &depotLocker, uint8_t tier, uint16_t itemId) const { + std::vector<std::shared_ptr<Item>> lockerItems; + const auto &[itemVector, itemMap] = requestLockerItems(depotLocker, false, tier); + uint16_t totalCount = 0; + for (const auto &item : itemVector) { + if (!item || item->getID() != itemId) { + continue; + } + + totalCount++; + lockerItems.emplace_back(item); + } + + return std::make_pair(lockerItems, totalCount); } -void Player::registerForgeHistoryDescription(ForgeHistory history) { - std::string successfulString = history.success ? "Successful" : "Unsuccessful"; - std::string historyTierString = history.tier > 0 ? "tier - 1" : "consumed"; - std::string price = history.bonus != 3 ? formatPrice(std::to_string(history.cost), true) : "0"; - std::stringstream detailsResponse; - auto itemId = Item::items.getItemIdByName(history.firstItemName); - const ItemType &itemType = Item::items[itemId]; - if (history.actionType == ForgeAction_t::FUSION) { - if (history.success) { - detailsResponse << fmt::format( - "{:s}{:s} <br><br>" - "Fusion partners:" - "<ul> " - "<li>" - "First item: {:s} {:s}, tier {:s}" - "</li>" - "<li>" - "Second item: {:s} {:s}, tier {:s}" - "</li>" - "</ul>" - "<br>" - "Result:" - "<ul> " - "<li>" - "First item: tier + 1" - "</li>" - "<li>" - "Second item: {:s}" - "</li>" - "</ul>" - "<br>" - "Invested:" - "<ul>" - "<li>" - "{:d} cores" - "</li>" - "<li>" - "{:d} dust" - "</li>" - "<li>" - "{:s} gold" - "</li>" - "</ul>", - successfulString, - history.convergence ? " (convergence)" : "", - itemType.article, itemType.name, std::to_string(history.tier), - itemType.article, itemType.name, std::to_string(history.tier), - history.bonus == 8 ? "unchanged" : "consumed", - history.coresCost, history.dustCost, price - ); +bool Player::saySpell(SpeakClasses type, const std::string &text, bool isGhostMode, const Spectators* spectatorsPtr, const Position* pos) { + if (text.empty()) { + g_logger().debug("{} - Spell text is empty for player {}", __FUNCTION__, getName()); + return false; + } + + if (!pos) { + pos = &getPosition(); + } + + Spectators spectators; + + if (!spectatorsPtr || spectatorsPtr->empty()) { + // This somewhat complex construct ensures that the cached Spectators + // is used if available and if it can be used, else a local vector is + // used (hopefully the compiler will optimize away the construction of + // the temporary when it's not used). + if (type != TALKTYPE_YELL && type != TALKTYPE_MONSTER_YELL) { + spectators.find<Creature>(*pos, false, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_Y, MAP_MAX_CLIENT_VIEW_PORT_Y); } else { - detailsResponse << fmt::format( - "{:s}{:s} <br><br>" - "Fusion partners:" - "<ul> " - "<li>" - "First item: {:s} {:s}, tier {:s}" - "</li>" - "<li>" - "Second item: {:s} {:s}, tier {:s}" - "</li>" - "</ul>" - "<br>" - "Result:" - "<ul> " - "<li>" - "First item: unchanged" - "</li>" - "<li>" - "Second item: {:s}" - "</li>" - "</ul>" - "<br>" - "Invested:" - "<ul>" - "<li>" - "{:d} cores" - "</li>" - "<li>" - "100 dust" - "</li>" - "<li>" - "{:s} gold" - "</li>" - "</ul>", - successfulString, - history.convergence ? " (convergence)" : "", - itemType.article, itemType.name, std::to_string(history.tier), - itemType.article, itemType.name, std::to_string(history.tier), - history.bonus == 8 ? "unchanged" : historyTierString, - history.coresCost, price - ); + spectators.find<Creature>(*pos, true, (MAP_MAX_CLIENT_VIEW_PORT_X + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_X + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_Y + 1) * 2, (MAP_MAX_CLIENT_VIEW_PORT_Y + 1) * 2); } - } else if (history.actionType == ForgeAction_t::TRANSFER) { - detailsResponse << fmt::format( - "{:s}{:s} <br><br>" - "Transfer partners:" - "<ul> " - "<li>" - "First item: {:s} {:s}, tier {:s}" - "</li>" - "<li>" - "Second item: {:s} {:s}, tier {:s}" - "</li>" - "</ul>" - "<br>" - "Result:" - "<ul> " - "<li>" - "First item: {:s} {:s}, tier {:s}" - "</li>" - "<li>" - "Second item: {:s} {:s}, {:s}" - "</li>" - "</ul>" - "<br>" - "Invested:" - "<ul>" - "<li>" - "1 cores" - "</li>" - "<li>" - "100 dust" - "</li>" - "<li>" - "{:s} gold" - "</li>" - "</ul>", - successfulString, - history.convergence ? " (convergence)" : "", - itemType.article, itemType.name, std::to_string(history.tier), - itemType.article, itemType.name, std::to_string(history.tier), - itemType.article, itemType.name, std::to_string(history.tier), - itemType.article, itemType.name, std::to_string(history.tier), - price - ); - } else if (history.actionType == ForgeAction_t::DUSTTOSLIVERS) { - detailsResponse << fmt::format("Converted {:d} dust to {:d} slivers.", history.cost, history.gained); - } else if (history.actionType == ForgeAction_t::SLIVERSTOCORES) { - history.actionType = ForgeAction_t::DUSTTOSLIVERS; - detailsResponse << fmt::format("Converted {:d} slivers to {:d} exalted core.", history.cost, history.gained); - } else if (history.actionType == ForgeAction_t::INCREASELIMIT) { - history.actionType = ForgeAction_t::DUSTTOSLIVERS; - detailsResponse << fmt::format("Spent {:d} dust to increase the dust limit to {:d}.", history.cost, history.gained + 1); } else { - detailsResponse << "(unknown)"; + spectators = (*spectatorsPtr); } - history.description = detailsResponse.str(); + int32_t valueEmote = 0; + // Send to client + for (const auto &spectator : spectators) { + if (const auto &tmpPlayer = spectator->getPlayer()) { + if (g_configManager().getBoolean(EMOTE_SPELLS)) { + valueEmote = tmpPlayer->getStorageValue(STORAGEVALUE_EMOTE); + } + if (!isGhostMode || tmpPlayer->canSeeCreature(static_self_cast<Player>())) { + if (valueEmote == 1) { + tmpPlayer->sendCreatureSay(static_self_cast<Player>(), TALKTYPE_MONSTER_SAY, text, pos); + } else { + tmpPlayer->sendCreatureSay(static_self_cast<Player>(), TALKTYPE_SPELL_USE, text, pos); + } + } + } + } - setForgeHistory(history); + // Execute lua event method + for (const auto &spectator : spectators) { + const auto &tmpPlayer = spectator->getPlayer(); + if (!tmpPlayer) { + continue; + } + + tmpPlayer->onCreatureSay(static_self_cast<Player>(), type, text); + } + return true; } -void Player::closeAllExternalContainers() { - if (openContainers.empty()) { - return; +void Player::triggerMomentum() { + double_t chance = 0; + if (const auto &item = getInventoryItem(CONST_SLOT_HEAD)) { + chance += item->getMomentumChance(); } - std::vector<std::shared_ptr<Container>> containerToClose; - for (const auto &it : openContainers) { - std::shared_ptr<Container> container = it.second.container; - if (!container) { + chance += m_wheelPlayer->getBonusData().momentum; + double_t randomChance = uniform_random(0, 10000) / 100.; + if (getZoneType() != ZONE_PROTECTION && hasCondition(CONDITION_INFIGHT) && ((OTSYS_TIME() / 1000) % 2) == 0 && chance > 0 && randomChance < chance) { + bool triggered = false; + auto it = conditions.begin(); + while (it != conditions.end()) { + const auto condItem = *it; + const ConditionType_t type = condItem->getType(); + constexpr auto maxu16 = std::numeric_limits<uint16_t>::max(); + const auto checkSpellId = condItem->getSubId(); + auto spellId = checkSpellId > maxu16 ? 0u : static_cast<uint16_t>(checkSpellId); + const int32_t ticks = condItem->getTicks(); + const int32_t newTicks = (ticks <= 2000) ? 0 : ticks - 2000; + triggered = true; + if (type == CONDITION_SPELLCOOLDOWN || (type == CONDITION_SPELLGROUPCOOLDOWN && spellId > SPELLGROUP_SUPPORT)) { + condItem->setTicks(newTicks); + type == CONDITION_SPELLGROUPCOOLDOWN ? sendSpellGroupCooldown(static_cast<SpellGroup_t>(spellId), newTicks) : sendSpellCooldown(spellId, newTicks); + } + ++it; + } + if (triggered) { + g_game().addMagicEffect(getPosition(), CONST_ME_HOURGLASS); + sendTextMessage(MESSAGE_ATTENTION, "Momentum was triggered."); + } + } +} + +void Player::clearCooldowns() { + auto it = conditions.begin(); + while (it != conditions.end()) { + const auto &condItem = *it; + if (!condItem) { + ++it; continue; } - if (container->getHoldingPlayer() != getPlayer()) { - containerToClose.push_back(container); + const ConditionType_t type = condItem->getType(); + constexpr auto maxu16 = std::numeric_limits<uint16_t>::max(); + const auto checkSpellId = condItem->getSubId(); + auto spellId = checkSpellId > maxu16 ? 0u : static_cast<uint16_t>(checkSpellId); + if (type == CONDITION_SPELLCOOLDOWN || type == CONDITION_SPELLGROUPCOOLDOWN) { + condItem->setTicks(0); + type == CONDITION_SPELLGROUPCOOLDOWN ? sendSpellGroupCooldown(static_cast<SpellGroup_t>(spellId), 0) : sendSpellCooldown(spellId, 0); + } + ++it; + } +} + +void Player::triggerTranscendance() { + if (wheel()->getOnThinkTimer(WheelOnThink_t::AVATAR_FORGE) > OTSYS_TIME()) { + return; + } + + const auto &item = getInventoryItem(CONST_SLOT_LEGS); + if (item == nullptr) { + return; + } + + const double_t chance = item->getTranscendenceChance(); + const double_t randomChance = uniform_random(0, 10000) / 100.; + if (getZoneType() != ZONE_PROTECTION && checkLastAggressiveActionWithin(2000) && ((OTSYS_TIME() / 1000) % 2) == 0 && chance > 0 && randomChance < chance) { + int64_t duration = g_configManager().getNumber(TRANSCENDANCE_AVATAR_DURATION); + const auto &outfitCondition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)->static_self_cast<ConditionOutfit>(); + Outfit_t outfit; + outfit.lookType = getVocation()->getAvatarLookType(); + outfitCondition->setOutfit(outfit); + addCondition(outfitCondition); + wheel()->setOnThinkTimer(WheelOnThink_t::AVATAR_FORGE, OTSYS_TIME() + duration); + g_game().addMagicEffect(getPosition(), CONST_ME_AVATAR_APPEAR); + + sendSkills(); + sendStats(); + sendBasicData(); + + sendTextMessage(MESSAGE_ATTENTION, "Transcendance was triggered."); + + // Send player data after transcendance timer expire + const auto &task = createPlayerTask( + std::max<uint32_t>(SCHEDULER_MINTICKS, duration), + [playerId = getID()] { + const auto &player = g_game().getPlayerByID(playerId); + if (player) { + player->sendSkills(); + player->sendStats(); + player->sendBasicData(); + } + }, + __FUNCTION__ + ); + g_dispatcher().scheduleEvent(task); + + wheel()->sendGiftOfLifeCooldown(); + g_game().reloadCreature(getPlayer()); + } +} + +// Forge system +void Player::forgeFuseItems(ForgeAction_t actionType, uint16_t firstItemId, uint8_t tier, uint16_t secondItemId, bool success, bool reduceTierLoss, bool convergence, uint8_t bonus, uint8_t coreCount) { + if (getFreeBackpackSlots() == 0) { + sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); + return; + } + + ForgeHistory history; + history.actionType = actionType; + history.tier = tier; + history.success = success; + history.tierLoss = reduceTierLoss; + + const auto &firstForgingItem = getForgeItemFromId(firstItemId, tier); + if (!firstForgingItem) { + g_logger().error("[Log 1] Player with name {} failed to fuse item with id {}", getName(), firstItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + auto returnValue = g_game().internalRemoveItem(firstForgingItem, 1); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 1] Failed to remove forge item {} from player with name {}", firstItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + const auto &secondForgingItem = getForgeItemFromId(secondItemId, tier); + if (!secondForgingItem) { + g_logger().error("[Log 2] Player with name {} failed to fuse item with id {}", getName(), secondItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + if (returnValue = g_game().internalRemoveItem(secondForgingItem, 1); + returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 2] Failed to remove forge item {} from player with name {}", secondItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto &exaltationChest = Item::CreateItem(ITEM_EXALTATION_CHEST, 1); + if (!exaltationChest) { + g_logger().error("Failed to create exaltation chest"); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + const auto &exaltationContainer = exaltationChest->getContainer(); + if (!exaltationContainer) { + g_logger().error("Failed to create exaltation container"); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto &firstForgedItem = Item::CreateItem(firstItemId, 1); + if (!firstForgedItem) { + g_logger().error("[Log 3] Player with name {} failed to fuse item with id {}", getName(), firstItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + returnValue = g_game().internalAddItem(exaltationContainer, firstForgedItem, INDEX_WHEREEVER); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 1] Failed to add forge item {} from player with name {}", firstItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + auto configKey = convergence ? FORGE_CONVERGENCE_FUSION_DUST_COST : FORGE_FUSION_DUST_COST; + auto dustCost = static_cast<uint64_t>(g_configManager().getNumber(configKey)); + if (convergence) { + firstForgedItem->setTier(tier + 1); + history.dustCost = dustCost; + setForgeDusts(getForgeDusts() - dustCost); + + uint64_t cost = 0; + for (const auto* itemClassification : g_game().getItemsClassifications()) { + if (itemClassification->id != firstForgingItem->getClassification()) { + continue; + } + + for (const auto &[mapTier, mapPrice] : itemClassification->tiers) { + if (mapTier == firstForgingItem->getTier() + 1) { + cost = mapPrice.convergenceFusionPrice; + break; + } + } + break; + } + if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { + g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_convergence_fuse" } }); + history.cost = cost; + } else { + firstForgedItem->setTier(tier); + const auto &secondForgedItem = Item::CreateItem(secondItemId, 1); + if (!secondForgedItem) { + g_logger().error("[Log 4] Player with name {} failed to fuse item with id {}", getName(), secondItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + secondForgedItem->setTier(tier); + returnValue = g_game().internalAddItem(exaltationContainer, secondForgedItem, INDEX_WHEREEVER); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 2] Failed to add forge item {} from player with name {}", secondItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + if (success) { + firstForgedItem->setTier(tier + 1); + + if (bonus != 1) { + history.dustCost = dustCost; + setForgeDusts(getForgeDusts() - dustCost); + } + if (bonus != 2) { + if (coreCount != 0 && !removeItemCountById(ITEM_FORGE_CORE, coreCount)) { + g_logger().error("[{}][Log 1] Failed to remove item 'id :{} count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), coreCount, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + history.coresCost = coreCount; + } + if (bonus != 3) { + uint64_t cost = 0; + for (const auto* itemClassification : g_game().getItemsClassifications()) { + if (itemClassification->id != firstForgedItem->getClassification()) { + continue; + } + if (!itemClassification->tiers.contains(firstForgedItem->getTier())) { + g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, firstForgedItem->getTier(), firstForgedItem->getClassification(), itemClassification->id); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + break; + } + cost = itemClassification->tiers.at(firstForgedItem->getTier()).regularPrice; + break; + } + if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { + g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_fuse" } }); + history.cost = cost; + } + + if (bonus == 4) { + if (tier > 0) { + secondForgedItem->setTier(tier - 1); + } + } else if (bonus == 6) { + secondForgedItem->setTier(tier + 1); + } else if (bonus == 7 && tier + 2 <= firstForgedItem->getClassification()) { + firstForgedItem->setTier(tier + 2); + } + + if (bonus != 4 && bonus != 5 && bonus != 6 && bonus != 8) { + returnValue = g_game().internalRemoveItem(secondForgedItem, 1); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 6] Failed to remove forge item {} from player with name {}", secondItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + } + } else { + auto isTierLost = uniform_random(1, 100) <= (reduceTierLoss ? g_configManager().getNumber(FORGE_TIER_LOSS_REDUCTION) : 100); + if (isTierLost) { + if (secondForgedItem->getTier() >= 1) { + secondForgedItem->setTier(tier - 1); + } else { + returnValue = g_game().internalRemoveItem(secondForgedItem, 1); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 7] Failed to remove forge item {} from player with name {}", secondItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + } + } + bonus = (isTierLost ? 0 : 8); + history.coresCost = coreCount; + + if (getForgeDusts() < dustCost) { + g_logger().error("[Log 7] Failed to remove fuse dusts from player with name {}", getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } else { + setForgeDusts(getForgeDusts() - dustCost); + } + + if (coreCount != 0 && !removeItemCountById(ITEM_FORGE_CORE, coreCount)) { + g_logger().error("[{}][Log 2] Failed to remove item 'id: {}, count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), coreCount, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + uint64_t cost = 0; + for (const auto* itemClassification : g_game().getItemsClassifications()) { + if (itemClassification->id != firstForgingItem->getClassification()) { + continue; + } + if (!itemClassification->tiers.contains(firstForgingItem->getTier() + 1)) { + g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, firstForgingItem->getTier() + 1, firstForgingItem->getClassification(), itemClassification->id); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + break; + } + cost = itemClassification->tiers.at(firstForgingItem->getTier() + 1).regularPrice; + break; + } + if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { + g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_fuse" } }); + + history.cost = cost; + } + } + + returnValue = g_game().internalAddItem(static_self_cast<Player>(), exaltationContainer, INDEX_WHEREEVER); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("Failed to add exaltation chest to player with name {}", getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + history.firstItemName = firstForgingItem->getName(); + history.secondItemName = secondForgingItem->getName(); + history.bonus = bonus; + history.createdAt = getTimeNow(); + history.convergence = convergence; + registerForgeHistoryDescription(history); + + sendForgeResult(actionType, firstItemId, tier, secondItemId, tier + 1, success, bonus, coreCount, convergence); +} + +void Player::forgeTransferItemTier(ForgeAction_t actionType, uint16_t donorItemId, uint8_t tier, uint16_t receiveItemId, bool convergence) { + if (getFreeBackpackSlots() == 0) { + sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); + return; + } + + ForgeHistory history; + history.actionType = actionType; + history.tier = tier; + history.success = true; + + const auto &donorItem = getForgeItemFromId(donorItemId, tier); + if (!donorItem) { + g_logger().error("[Log 1] Player with name {} failed to transfer item with id {}", getName(), donorItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + auto returnValue = g_game().internalRemoveItem(donorItem, 1); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 1] Failed to remove transfer item {} from player with name {}", donorItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto &receiveItem = getForgeItemFromId(receiveItemId, 0); + if (!receiveItem) { + g_logger().error("[Log 2] Player with name {} failed to transfer item with id {}", getName(), receiveItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + if (returnValue = g_game().internalRemoveItem(receiveItem, 1); + returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 2] Failed to remove transfer item {} from player with name {}", receiveItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto &exaltationChest = Item::CreateItem(ITEM_EXALTATION_CHEST, 1); + if (!exaltationChest) { + g_logger().error("Exaltation chest is nullptr"); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + const auto &exaltationContainer = exaltationChest->getContainer(); + if (!exaltationContainer) { + g_logger().error("Exaltation container is nullptr"); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto &newReceiveItem = Item::CreateItem(receiveItemId, 1); + if (!newReceiveItem) { + g_logger().error("[Log 6] Player with name {} failed to fuse item with id {}", getName(), receiveItemId); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + auto configKey = convergence ? FORGE_CONVERGENCE_TRANSFER_DUST_COST : FORGE_TRANSFER_DUST_COST; + if (getForgeDusts() < g_configManager().getNumber(configKey)) { + g_logger().error("[Log 8] Failed to remove transfer dusts from player with name {}", getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + setForgeDusts(getForgeDusts() - g_configManager().getNumber(configKey)); + + if (convergence) { + newReceiveItem->setTier(tier); + } else { + newReceiveItem->setTier(tier - 1); + } + returnValue = g_game().internalAddItem(exaltationContainer, newReceiveItem, INDEX_WHEREEVER); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 7] Failed to add forge item {} from player with name {}", receiveItemId, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + uint8_t coresAmount = 0; + uint64_t cost = 0; + for (const auto &itemClassification : g_game().getItemsClassifications()) { + if (itemClassification->id != donorItem->getClassification()) { + continue; + } + if (!itemClassification->tiers.contains(donorItem->getTier())) { + g_logger().error("[{}] Failed to find tier {} for item {} in classification {}", __FUNCTION__, donorItem->getTier(), donorItem->getClassification(), itemClassification->id); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + break; + } + + const uint8_t toTier = convergence ? donorItem->getTier() : donorItem->getTier() - 1; + auto tierPriecs = itemClassification->tiers.at(toTier); + cost = convergence ? tierPriecs.convergenceTransferPrice : tierPriecs.regularPrice; + coresAmount = tierPriecs.corePrice; + break; + } + + if (!removeItemCountById(ITEM_FORGE_CORE, coresAmount)) { + g_logger().error("[{}] Failed to remove item 'id: {}, count: {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_CORE), 1, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + if (!g_game().removeMoney(static_self_cast<Player>(), cost, 0, true)) { + g_logger().error("[{}] Failed to remove {} gold from player with name {}", __FUNCTION__, cost, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + history.cost = cost; + g_metrics().addCounter("balance_decrease", cost, { { "player", getName() }, { "context", "forge_transfer" } }); + + returnValue = g_game().internalAddItem(static_self_cast<Player>(), exaltationContainer, INDEX_WHEREEVER); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("[Log 10] Failed to add forge item {} from player with name {}", fmt::underlying(ITEM_EXALTATION_CHEST), getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + history.firstItemName = Item::items[donorItemId].name; + history.secondItemName = newReceiveItem->getName(); + history.createdAt = getTimeNow(); + history.convergence = convergence; + registerForgeHistoryDescription(history); + + sendForgeResult(actionType, donorItemId, tier, receiveItemId, convergence ? tier : tier - 1, true, 0, 0, convergence); +} + +void Player::forgeResourceConversion(ForgeAction_t actionType) { + ForgeHistory history; + history.actionType = actionType; + history.success = true; + + ReturnValue returnValue = RETURNVALUE_NOERROR; + if (actionType == ForgeAction_t::DUSTTOSLIVERS) { + auto dusts = getForgeDusts(); + auto cost = static_cast<uint16_t>(g_configManager().getNumber(FORGE_COST_ONE_SLIVER) * g_configManager().getNumber(FORGE_SLIVER_AMOUNT)); + if (cost > dusts) { + g_logger().error("[{}] Not enough dust", __FUNCTION__); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + auto itemCount = static_cast<uint16_t>(g_configManager().getNumber(FORGE_SLIVER_AMOUNT)); + const auto &item = Item::CreateItem(ITEM_FORGE_SLIVER, itemCount); + returnValue = g_game().internalPlayerAddItem(static_self_cast<Player>(), item); + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("Failed to add {} slivers to player with name {}", itemCount, getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + history.cost = cost; + history.gained = 3; + setForgeDusts(dusts - cost); + } else if (actionType == ForgeAction_t::SLIVERSTOCORES) { + const auto &[sliverCount, coreCount] = getForgeSliversAndCores(); + auto cost = static_cast<uint16_t>(g_configManager().getNumber(FORGE_CORE_COST)); + if (cost > sliverCount) { + g_logger().error("[{}] Not enough sliver", __FUNCTION__); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + if (!removeItemCountById(ITEM_FORGE_SLIVER, cost)) { + g_logger().error("[{}] Failed to remove item 'id: {}, count {}' from player {}", __FUNCTION__, fmt::underlying(ITEM_FORGE_SLIVER), cost, getName()); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + if (const auto &item = Item::CreateItem(ITEM_FORGE_CORE, 1); + item) { + returnValue = g_game().internalPlayerAddItem(static_self_cast<Player>(), item); + } + if (returnValue != RETURNVALUE_NOERROR) { + g_logger().error("Failed to add one core to player with name {}", getName()); + sendCancelMessage(getReturnMessage(returnValue)); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + history.cost = cost; + history.gained = 1; + } else { + auto dustLevel = getForgeDustLevel(); + if (dustLevel >= g_configManager().getNumber(FORGE_MAX_DUST)) { + g_logger().error("[{}] Maximum level reached", __FUNCTION__); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + const auto upgradeCost = dustLevel - 75; + if (const auto dusts = getForgeDusts(); + upgradeCost > dusts) { + g_logger().error("[{}] Not enough dust", __FUNCTION__); + sendForgeError(RETURNVALUE_CONTACTADMINISTRATOR); + return; + } + + history.cost = upgradeCost; + history.gained = dustLevel; + removeForgeDusts(upgradeCost); + addForgeDustLevel(1); + } + + history.createdAt = getTimeNow(); + registerForgeHistoryDescription(history); + sendForgingData(); +} + +void Player::forgeHistory(uint8_t page) const { + sendForgeHistory(page); +} + +void Player::sendOpenForge() const { + if (client) { + client->sendOpenForge(); + } +} + +void Player::sendForgeError(ReturnValue returnValue) const { + if (client) { + client->sendForgeError(returnValue); + } +} + +void Player::sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId, uint8_t leftTier, uint16_t rightItemId, uint8_t rightTier, bool success, uint8_t bonus, uint8_t coreCount, bool convergence) const { + if (client) { + client->sendForgeResult(actionType, leftItemId, leftTier, rightItemId, rightTier, success, bonus, coreCount, convergence); + } +} + +void Player::sendForgeHistory(uint8_t page) const { + if (client) { + client->sendForgeHistory(page); + } +} + +void Player::closeForgeWindow() const { + if (client) { + client->closeForgeWindow(); + } +} + +void Player::setForgeDusts(uint64_t amount) { + forgeDusts = amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); + } +} + +void Player::addForgeDusts(uint64_t amount) { + forgeDusts += amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); + } +} + +void Player::removeForgeDusts(uint64_t amount) { + forgeDusts = std::max<uint64_t>(0, forgeDusts - amount); + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); + } +} + +uint64_t Player::getForgeDusts() const { + return forgeDusts; +} + +void Player::addForgeDustLevel(uint64_t amount) { + forgeDustLevel += amount; + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); + } +} + +void Player::removeForgeDustLevel(uint64_t amount) { + forgeDustLevel = std::max<uint64_t>(0, forgeDustLevel - amount); + if (client) { + client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); + } +} + +uint64_t Player::getForgeDustLevel() const { + return forgeDustLevel; +} + +std::vector<ForgeHistory> &Player::getForgeHistory() { + return forgeHistoryVector; +} + +void Player::setForgeHistory(const ForgeHistory &history) { + forgeHistoryVector.emplace_back(history); +} + +void Player::registerForgeHistoryDescription(ForgeHistory history) { + std::string successfulString = history.success ? "Successful" : "Unsuccessful"; + std::string historyTierString = history.tier > 0 ? "tier - 1" : "consumed"; + std::string price = history.bonus != 3 ? formatPrice(std::to_string(history.cost), true) : "0"; + std::stringstream detailsResponse; + auto itemId = Item::items.getItemIdByName(history.firstItemName); + const ItemType &itemType = Item::items[itemId]; + if (history.actionType == ForgeAction_t::FUSION) { + if (history.success) { + detailsResponse << fmt::format( + "{:s}{:s} <br><br>" + "Fusion partners:" + "<ul> " + "<li>" + "First item: {:s} {:s}, tier {:s}" + "</li>" + "<li>" + "Second item: {:s} {:s}, tier {:s}" + "</li>" + "</ul>" + "<br>" + "Result:" + "<ul> " + "<li>" + "First item: tier + 1" + "</li>" + "<li>" + "Second item: {:s}" + "</li>" + "</ul>" + "<br>" + "Invested:" + "<ul>" + "<li>" + "{:d} cores" + "</li>" + "<li>" + "{:d} dust" + "</li>" + "<li>" + "{:s} gold" + "</li>" + "</ul>", + successfulString, + history.convergence ? " (convergence)" : "", + itemType.article, itemType.name, std::to_string(history.tier), + itemType.article, itemType.name, std::to_string(history.tier), + history.bonus == 8 ? "unchanged" : "consumed", + history.coresCost, history.dustCost, price + ); + } else { + detailsResponse << fmt::format( + "{:s}{:s} <br><br>" + "Fusion partners:" + "<ul> " + "<li>" + "First item: {:s} {:s}, tier {:s}" + "</li>" + "<li>" + "Second item: {:s} {:s}, tier {:s}" + "</li>" + "</ul>" + "<br>" + "Result:" + "<ul> " + "<li>" + "First item: unchanged" + "</li>" + "<li>" + "Second item: {:s}" + "</li>" + "</ul>" + "<br>" + "Invested:" + "<ul>" + "<li>" + "{:d} cores" + "</li>" + "<li>" + "100 dust" + "</li>" + "<li>" + "{:s} gold" + "</li>" + "</ul>", + successfulString, + history.convergence ? " (convergence)" : "", + itemType.article, itemType.name, std::to_string(history.tier), + itemType.article, itemType.name, std::to_string(history.tier), + history.bonus == 8 ? "unchanged" : historyTierString, + history.coresCost, price + ); + } + } else if (history.actionType == ForgeAction_t::TRANSFER) { + detailsResponse << fmt::format( + "{:s}{:s} <br><br>" + "Transfer partners:" + "<ul> " + "<li>" + "First item: {:s} {:s}, tier {:s}" + "</li>" + "<li>" + "Second item: {:s} {:s}, tier {:s}" + "</li>" + "</ul>" + "<br>" + "Result:" + "<ul> " + "<li>" + "First item: {:s} {:s}, tier {:s}" + "</li>" + "<li>" + "Second item: {:s} {:s}, {:s}" + "</li>" + "</ul>" + "<br>" + "Invested:" + "<ul>" + "<li>" + "1 cores" + "</li>" + "<li>" + "100 dust" + "</li>" + "<li>" + "{:s} gold" + "</li>" + "</ul>", + successfulString, + history.convergence ? " (convergence)" : "", + itemType.article, itemType.name, std::to_string(history.tier), + itemType.article, itemType.name, std::to_string(history.tier), + itemType.article, itemType.name, std::to_string(history.tier), + itemType.article, itemType.name, std::to_string(history.tier), + price + ); + } else if (history.actionType == ForgeAction_t::DUSTTOSLIVERS) { + detailsResponse << fmt::format("Converted {:d} dust to {:d} slivers.", history.cost, history.gained); + } else if (history.actionType == ForgeAction_t::SLIVERSTOCORES) { + history.actionType = ForgeAction_t::DUSTTOSLIVERS; + detailsResponse << fmt::format("Converted {:d} slivers to {:d} exalted core.", history.cost, history.gained); + } else if (history.actionType == ForgeAction_t::INCREASELIMIT) { + history.actionType = ForgeAction_t::DUSTTOSLIVERS; + detailsResponse << fmt::format("Spent {:d} dust to increase the dust limit to {:d}.", history.cost, history.gained + 1); + } else { + detailsResponse << "(unknown)"; + } + + history.description = detailsResponse.str(); + + setForgeHistory(history); +} + +// Quickloot + +void Player::openPlayerContainers() { + std::vector<std::pair<uint8_t, std::shared_ptr<Container>>> openContainersList; + + for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { + const auto &item = inventory[i]; + if (!item) { + continue; + } + + const auto &itemContainer = item->getContainer(); + if (itemContainer) { + const auto &cid = item->getAttribute<int64_t>(ItemAttribute_t::OPENCONTAINER); + if (cid > 0) { + openContainersList.emplace_back(cid, itemContainer); + } + for (ContainerIterator it = itemContainer->iterator(); it.hasNext(); it.advance()) { + const auto &subContainer = (*it)->getContainer(); + if (subContainer) { + const auto &subcid = (*it)->getAttribute<uint8_t>(ItemAttribute_t::OPENCONTAINER); + if (subcid > 0) { + openContainersList.emplace_back(subcid, subContainer); + } + } + } + } + } + + std::ranges::sort(openContainersList, [](const std::pair<uint8_t, std::shared_ptr<Container>> &left, const std::pair<uint8_t, std::shared_ptr<Container>> &right) { + return left.first < right.first; + }); + + for (const auto &[containerId, container] : openContainersList) { + addContainer(containerId - 1, container); + onSendContainer(container); + } +} + +// Quickloot + +void Player::sendLootContainers() const { + if (client) { + client->sendLootContainers(); + } +} + +void Player::sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const { + if (client) { + client->sendSingleSoundEffect(pos, id, source); + } +} + +void Player::sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundId, SourceEffect_t mainSource, SoundEffect_t secondarySoundId, SourceEffect_t secondarySource) const { + if (client) { + client->sendDoubleSoundEffect(pos, mainSoundId, mainSource, secondarySoundId, secondarySource); + } +} + +SoundEffect_t Player::getAttackSoundEffect() const { + const auto &tool = getWeapon(); + if (tool == nullptr) { + return SoundEffect_t::HUMAN_CLOSE_ATK_FIST; + } + + const ItemType &it = Item::items[tool->getID()]; + if (it.weaponType == WEAPON_NONE || it.weaponType == WEAPON_SHIELD) { + return SoundEffect_t::HUMAN_CLOSE_ATK_FIST; + } + + switch (it.weaponType) { + case WEAPON_AXE: { + return SoundEffect_t::MELEE_ATK_AXE; + } + case WEAPON_SWORD: { + return SoundEffect_t::MELEE_ATK_SWORD; + } + case WEAPON_CLUB: { + return SoundEffect_t::MELEE_ATK_CLUB; + } + case WEAPON_AMMO: + case WEAPON_DISTANCE: { + if (tool->getAmmoType() == AMMO_BOLT) { + return SoundEffect_t::DIST_ATK_CROSSBOW; + } + if (tool->getAmmoType() == AMMO_ARROW) { + return SoundEffect_t::DIST_ATK_BOW; + } + return SoundEffect_t::DIST_ATK_THROW; + + break; + } + case WEAPON_WAND: { + return SoundEffect_t::MAGICAL_RANGE_ATK; + } + default: { + return SoundEffect_t::SILENCE; + } + } + + return SoundEffect_t::SILENCE; +} + +SoundEffect_t Player::getHitSoundEffect() const { + // Distance sound effects + const auto &tool = getWeapon(); + if (tool == nullptr) { + return SoundEffect_t::SILENCE; + } + + switch (const auto &it = Item::items[tool->getID()]; it.weaponType) { + case WEAPON_AMMO: { + if (it.ammoType == AMMO_BOLT) { + return SoundEffect_t::DIST_ATK_CROSSBOW_SHOT; + } + if (it.ammoType == AMMO_ARROW) { + if (it.shootType == CONST_ANI_BURSTARROW) { + return SoundEffect_t::BURST_ARROW_EFFECT; + } + if (it.shootType == CONST_ANI_DIAMONDARROW) { + return SoundEffect_t::DIAMOND_ARROW_EFFECT; + } + } else { + return SoundEffect_t::DIST_ATK_THROW_SHOT; + } + } + case WEAPON_DISTANCE: { + if (tool->getAmmoType() == AMMO_BOLT) { + return SoundEffect_t::DIST_ATK_CROSSBOW_SHOT; + } + if (tool->getAmmoType() == AMMO_ARROW) { + return SoundEffect_t::DIST_ATK_BOW_SHOT; + } + return SoundEffect_t::DIST_ATK_THROW_SHOT; + } + case WEAPON_WAND: { + // Separate between wand and rod here + // return SoundEffect_t::DIST_ATK_ROD_SHOT; + return SoundEffect_t::DIST_ATK_WAND_SHOT; + } + default: { + return SoundEffect_t::SILENCE; + } + } // switch + + return SoundEffect_t::SILENCE; +} + +// event methods + +void Player::onUpdateTileItem(const std::shared_ptr<Tile> &updateTile, const Position &pos, const std::shared_ptr<Item> &oldItem, const ItemType &oldType, const std::shared_ptr<Item> &newItem, const ItemType &newType) { + Creature::onUpdateTileItem(updateTile, pos, oldItem, oldType, newItem, newType); + + if (oldItem != newItem) { + onRemoveTileItem(updateTile, pos, oldType, oldItem); + } + + if (tradeState != TRADE_TRANSFER) { + if (tradeItem && oldItem == tradeItem) { + g_game().internalCloseTrade(getPlayer()); + } + } +} + +void Player::onRemoveTileItem(const std::shared_ptr<Tile> &fromTile, const Position &pos, const ItemType &iType, const std::shared_ptr<Item> &item) { + Creature::onRemoveTileItem(fromTile, pos, iType, item); + + if (tradeState != TRADE_TRANSFER) { + checkTradeState(item); + + if (tradeItem) { + const auto &container = item->getContainer(); + if (container && container->isHoldingItem(tradeItem)) { + g_game().internalCloseTrade(static_self_cast<Player>()); + } + } + } + + checkLootContainers(item->getContainer()); +} + +void Player::onCreatureAppear(const std::shared_ptr<Creature> &creature, bool isLogin) { + Creature::onCreatureAppear(creature, isLogin); + + if (isLogin && creature == getPlayer()) { + onEquipInventory(); + + // Refresh bosstiary tracker onLogin + refreshCyclopediaMonsterTracker(true); + // Refresh bestiary tracker onLogin + refreshCyclopediaMonsterTracker(false); + + for (const auto &condition : storedConditionList) { + addCondition(condition); + } + storedConditionList.clear(); + + updateRegeneration(); + + const auto &bed = g_game().getBedBySleeper(guid); + if (bed) { + bed->wakeUp(static_self_cast<Player>()); + } + + auto version = client->oldProtocol ? getProtocolVersion() : CLIENT_VERSION; + g_logger().info("{} has logged in. (Protocol: {})", name, version); + + if (guild) { + guild->addMember(static_self_cast<Player>()); + } + + int32_t offlineTime; + if (getLastLogout() != 0) { + // Not counting more than 21 days to prevent overflow when multiplying with 1000 (for milliseconds). + offlineTime = std::min<int32_t>(time(nullptr) - getLastLogout(), 86400 * 21); + } else { + offlineTime = 0; + } + + for (const auto &condition : getMuteConditions()) { + condition->setTicks(condition->getTicks() - (offlineTime * 1000)); + if (condition->getTicks() <= 0) { + removeCondition(condition); + } + } + + g_game().checkPlayersRecord(); + if (getLevel() < g_configManager().getNumber(ADVENTURERSBLESSING_LEVEL) && getVocationId() > VOCATION_NONE) { + for (uint8_t i = 2; i <= 6; i++) { + if (!hasBlessing(i)) { + addBlessing(i, 1); + } + } + sendBlessStatus(); + } + + if (getCurrentMount() != 0) { + toggleMount(true); + } + + g_game().changePlayerSpeed(static_self_cast<Player>(), 0); + } +} + +void Player::onRemoveCreature(const std::shared_ptr<Creature> &creature, bool isLogout) { + Creature::onRemoveCreature(creature, isLogout); + + if (const auto &player = getPlayer(); player == creature) { + if (isLogout) { + onDeEquipInventory(); + + if (m_party) { + m_party->leaveParty(player, true); + } + if (guild) { + guild->removeMember(player); + } + + g_game().removePlayerUniqueLogin(player); + loginPosition = getPosition(); + lastLogout = time(nullptr); + g_logger().info("{} has logged out", getName()); + g_chat().removeUserFromAllChannels(player); + clearPartyInvitations(); + } + + if (eventWalk != 0) { + setFollowCreature(nullptr); + } + + if (tradePartner) { + g_game().internalCloseTrade(player); + } + + closeShopWindow(); + + g_saveManager().savePlayer(player); + } + + if (creature == shopOwner) { + setShopOwner(nullptr); + sendCloseShop(); + } +} + +void Player::onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) { + Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); + + const auto &followCreature = getFollowCreature(); + if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) { + isUpdatingPath = false; + g_game().updateCreatureWalk(getID()); // internally uses addEventWalk. + } + + if (creature != getPlayer()) { + return; + } + + if (tradeState != TRADE_TRANSFER) { + // check if we should close trade + if (tradeItem && !Position::areInRange<1, 1, 0>(tradeItem->getPosition(), getPosition())) { + g_game().internalCloseTrade(getPlayer()); + } + + if (tradePartner && !Position::areInRange<2, 2, 0>(tradePartner->getPosition(), getPosition())) { + g_game().internalCloseTrade(getPlayer()); + } + } + + // close modal windows + if (!modalWindows.empty()) { + // TODO: This shouldn't be hardcoded + for (const uint32_t modalWindowId : modalWindows) { + if (modalWindowId == std::numeric_limits<uint32_t>::max()) { + sendTextMessage(MESSAGE_EVENT_ADVANCE, "Offline training aborted."); + break; + } + } + modalWindows.clear(); + } + + // leave market + if (inMarket) { + inMarket = false; + } + + if (m_party) { + m_party->updateSharedExperience(); + m_party->updatePlayerStatus(getPlayer(), oldPos, newPos); + } + + if (teleport || oldPos.z != newPos.z) { + int32_t ticks = g_configManager().getNumber(STAIRHOP_DELAY); + if (ticks > 0) { + if (const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks, 0)) { + addCondition(condition); + } + } + } +} + +void Player::onEquipInventory() { + for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { + const auto &item = inventory[slot]; + if (item) { + item->startDecaying(); + g_moveEvents().onPlayerEquip(getPlayer(), item, static_cast<Slots_t>(slot), false); + } + } +} + +void Player::onDeEquipInventory() { + for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { + const auto &item = inventory[slot]; + if (item) { + g_moveEvents().onPlayerDeEquip(getPlayer(), item, static_cast<Slots_t>(slot)); + } + } +} + +void Player::onAttackedCreatureDisappear(bool isLogout) { + sendCancelTarget(); + + if (!isLogout) { + sendTextMessage(MESSAGE_FAILURE, "Target lost."); + } +} + +void Player::onFollowCreatureDisappear(bool isLogout) { + sendCancelTarget(); + + if (!isLogout) { + sendTextMessage(MESSAGE_FAILURE, "Target lost."); + } +} + +// container +// container + +void Player::onAddContainerItem(const std::shared_ptr<Item> &item) { + checkTradeState(item); +} + +void Player::onUpdateContainerItem(const std::shared_ptr<Container> &container, const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem) { + if (oldItem != newItem) { + onRemoveContainerItem(container, oldItem); + } + + if (tradeState != TRADE_TRANSFER) { + checkTradeState(oldItem); + } +} + +void Player::onRemoveContainerItem(const std::shared_ptr<Container> &container, const std::shared_ptr<Item> &item) { + if (tradeState != TRADE_TRANSFER) { + checkTradeState(item); + + if (tradeItem) { + if (tradeItem->getParent() != container && container->isHoldingItem(tradeItem)) { + g_game().internalCloseTrade(static_self_cast<Player>()); + } + } + } + + checkLootContainers(item->getContainer()); +} + +void Player::onCloseContainer(const std::shared_ptr<Container> &container) { + if (!client) { + return; + } + + for (const auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container == container) { + client->sendCloseContainer(containerId); + } + } +} + +void Player::onSendContainer(const std::shared_ptr<Container> &container) { + if (!client || !container) { + return; + } + + const bool hasParent = container->hasParent(); + for (const auto &[containerId, containerInfo] : openContainers) { + if (containerInfo.container == container) { + client->sendContainer(containerId, container, hasParent, containerInfo.index); + } + } +} + +// close container and its child containers + +void Player::autoCloseContainers(const std::shared_ptr<Container> &container) { + std::vector<uint32_t> closeList; + for (const auto &[containerId, containerInfo] : openContainers) { + auto tmpContainer = containerInfo.container; + while (tmpContainer) { + if (tmpContainer->isRemoved() || tmpContainer == container) { + closeList.emplace_back(containerId); + break; + } + + tmpContainer = std::dynamic_pointer_cast<Container>(tmpContainer->getParent()); + } + } + + for (const uint32_t containerId : closeList) { + closeContainer(containerId); + if (client) { + client->sendCloseContainer(containerId); + } + } +} + +// inventory +// inventory + +void Player::onUpdateInventoryItem(const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem) { + if (oldItem != newItem) { + onRemoveInventoryItem(oldItem); + } + + if (tradeState != TRADE_TRANSFER) { + checkTradeState(oldItem); + } +} + +void Player::onRemoveInventoryItem(const std::shared_ptr<Item> &item) { + if (tradeState != TRADE_TRANSFER) { + checkTradeState(item); + + if (tradeItem) { + const auto &container = item->getContainer(); + if (container && container->isHoldingItem(tradeItem)) { + g_game().internalCloseTrade(static_self_cast<Player>()); + } } } - for (const std::shared_ptr<Container> &container : containerToClose) { - autoCloseContainers(container); - } + checkLootContainers(item->getContainer()); } -SoundEffect_t Player::getHitSoundEffect() const { - // Distance sound effects - std::shared_ptr<Item> tool = getWeapon(); - if (tool == nullptr) { - return SoundEffect_t::SILENCE; +uint64_t Player::getItemCustomPrice(uint16_t itemId, bool buyPrice) const { + auto it = itemPriceMap.find(itemId); + if (it != itemPriceMap.end()) { + return it->second; } - switch (const auto &it = Item::items[tool->getID()]; it.weaponType) { - case WEAPON_AMMO: { - if (it.ammoType == AMMO_BOLT) { - return SoundEffect_t::DIST_ATK_CROSSBOW_SHOT; - } else if (it.ammoType == AMMO_ARROW) { - if (it.shootType == CONST_ANI_BURSTARROW) { - return SoundEffect_t::BURST_ARROW_EFFECT; - } else if (it.shootType == CONST_ANI_DIAMONDARROW) { - return SoundEffect_t::DIAMOND_ARROW_EFFECT; - } - } else { - return SoundEffect_t::DIST_ATK_THROW_SHOT; - } - } - case WEAPON_DISTANCE: { - if (tool->getAmmoType() == AMMO_BOLT) { - return SoundEffect_t::DIST_ATK_CROSSBOW_SHOT; - } else if (tool->getAmmoType() == AMMO_ARROW) { - return SoundEffect_t::DIST_ATK_BOW_SHOT; - } else { - return SoundEffect_t::DIST_ATK_THROW_SHOT; - } - } - case WEAPON_WAND: { - // Separate between wand and rod here - // return SoundEffect_t::DIST_ATK_ROD_SHOT; - return SoundEffect_t::DIST_ATK_WAND_SHOT; - } - default: { - return SoundEffect_t::SILENCE; - } - } // switch - - return SoundEffect_t::SILENCE; + const std::map<uint16_t, uint64_t> itemMap { { itemId, 1 } }; + return g_game().getItemMarketPrice(itemMap, buyPrice); } -SoundEffect_t Player::getAttackSoundEffect() const { - std::shared_ptr<Item> tool = getWeapon(); - if (tool == nullptr) { - return SoundEffect_t::HUMAN_CLOSE_ATK_FIST; +uint16_t Player::getFreeBackpackSlots() const { + const auto &thing = getThing(CONST_SLOT_BACKPACK); + if (!thing) { + return 0; } - const ItemType &it = Item::items[tool->getID()]; - if (it.weaponType == WEAPON_NONE || it.weaponType == WEAPON_SHIELD) { - return SoundEffect_t::HUMAN_CLOSE_ATK_FIST; + const auto &backpack = thing->getContainer(); + if (!backpack) { + return 0; } - switch (it.weaponType) { - case WEAPON_AXE: { - return SoundEffect_t::MELEE_ATK_AXE; - } - case WEAPON_SWORD: { - return SoundEffect_t::MELEE_ATK_SWORD; - } - case WEAPON_CLUB: { - return SoundEffect_t::MELEE_ATK_CLUB; - } - case WEAPON_AMMO: - case WEAPON_DISTANCE: { - if (tool->getAmmoType() == AMMO_BOLT) { - return SoundEffect_t::DIST_ATK_CROSSBOW; - } else if (tool->getAmmoType() == AMMO_ARROW) { - return SoundEffect_t::DIST_ATK_BOW; - } else { - return SoundEffect_t::DIST_ATK_THROW; - } - - break; - } - case WEAPON_WAND: { - return SoundEffect_t::MAGICAL_RANGE_ATK; - } - default: { - return SoundEffect_t::SILENCE; - } - } + const uint16_t counter = std::max<uint16_t>(0, backpack->getFreeSlots()); - return SoundEffect_t::SILENCE; + return counter; } -bool Player::canAutoWalk(const Position &toPosition, const std::function<void()> &function, uint32_t delay /* = 500*/) { +bool Player::canAutoWalk(const Position &toPosition, const std::function<void()> &function, uint32_t delay) { if (!Position::areInRange<1, 1>(getPosition(), toPosition)) { // Check if can walk to the toPosition and send event to use function std::vector<Direction> listDir; @@ -7890,7 +10070,15 @@ bool Player::canAutoWalk(const Position &toPosition, const std::function<void()> return false; } +void Player::sendMessageDialog(const std::string &message) const { + if (client) { + client->sendMessageDialog(message); + } +} + +// Account // Account + bool Player::setAccount(uint32_t accountId) { if (account) { g_logger().warn("Account was already set!"); @@ -7898,11 +10086,11 @@ bool Player::setAccount(uint32_t accountId) { } account = std::make_shared<Account>(accountId); - return AccountErrors_t::Ok == enumFromValue<AccountErrors_t>(account->load()); + return AccountErrors_t::Ok == account->load(); } uint8_t Player::getAccountType() const { - return static_cast<uint8_t>(account ? account->getAccountType() : static_cast<uint8_t>(AccountType::ACCOUNT_TYPE_NORMAL)); + return account ? account->getAccountType() : AccountType::ACCOUNT_TYPE_NORMAL; } uint32_t Player::getAccountId() const { @@ -7913,133 +10101,108 @@ std::shared_ptr<Account> Player::getAccount() const { return account; } -/******************************************************************************* - * Hazard system - ******************************************************************************/ +// Prey system -void Player::setHazardSystemPoints(int32_t count) { - if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { - return; - } - addStorageValue(STORAGEVALUE_HAZARDCOUNT, std::max<int32_t>(0, std::min<int32_t>(0xFFFF, count)), true); - reloadHazardSystemPointsCounter = true; - if (count > 0) { - setIcon("hazard", CreatureIcon(CreatureIconQuests_t::Hazard, count)); - } else { - removeIcon("hazard"); +void Player::initializePrey() { + if (preys.empty()) { + for (uint8_t slotId = PreySlot_First; slotId <= PreySlot_Last; slotId++) { + auto slot = std::make_unique<PreySlot>(static_cast<PreySlot_t>(slotId)); + if (!g_configManager().getBoolean(PREY_ENABLED)) { + slot->state = PreyDataState_Inactive; + } else if (slot->id == PreySlot_Three && !g_configManager().getBoolean(PREY_FREE_THIRD_SLOT)) { + slot->state = PreyDataState_Locked; + } else if (slot->id == PreySlot_Two && !isPremium()) { + slot->state = PreyDataState_Locked; + } else { + slot->state = PreyDataState_Selection; + slot->reloadMonsterGrid(getPreyBlackList(), getLevel()); + } + + setPreySlotClass(slot); + } } } -void Player::parseAttackRecvHazardSystem(CombatDamage &damage, std::shared_ptr<Monster> monster) { - if (!monster || !monster->getHazard()) { - return; - } +void Player::removePreySlotById(PreySlot_t slotid) { + const auto it = std::ranges::remove_if(preys, [slotid](const auto &preyIt) { + return preyIt->id == slotid; + }).begin(); - if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { - return; - } + preys.erase(it, preys.end()); +} - if (damage.primary.type == COMBAT_HEALING) { - return; - } +/******************************************************************************* + * Hazard system + ******************************************************************************/ - auto points = getHazardSystemPoints(); - if (m_party) { - for (const auto &partyMember : m_party->getMembers()) { - if (partyMember && partyMember->getHazardSystemPoints() < points) { - points = partyMember->getHazardSystemPoints(); - } - } +void Player::setBossPoints(uint32_t amount) { + bossPoints = amount; +} - if (m_party->getLeader() && m_party->getLeader()->getHazardSystemPoints() < points) { - points = m_party->getLeader()->getHazardSystemPoints(); - } - } +void Player::addBossPoints(uint32_t amount) { + bossPoints += amount; +} - if (points == 0) { - return; - } +void Player::removeBossPoints(uint32_t amount) { + bossPoints = std::max<uint32_t>(0, bossPoints - amount); +} - uint16_t stage = 0; - auto chance = static_cast<uint16_t>(normal_random(1, 10000)); - auto critChance = g_configManager().getNumber(HAZARD_CRITICAL_CHANCE); - // Critical chance - if (monster->getHazardSystemCrit() && (lastHazardSystemCriticalHit + g_configManager().getNumber(HAZARD_CRITICAL_INTERVAL)) <= OTSYS_TIME() && chance <= critChance && !damage.critical) { - damage.critical = true; - damage.extension = true; - damage.exString = "(Hazard)"; +uint32_t Player::getBossPoints() const { + return bossPoints; +} - stage = (points - 1) * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_CRITICAL_MULTIPLIER)); - damage.primary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * (5000 + stage)) / 10000)); - damage.secondary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * (5000 + stage)) / 10000)); - lastHazardSystemCriticalHit = OTSYS_TIME(); +void Player::sendBosstiaryCooldownTimer() const { + if (client) { + client->sendBosstiaryCooldownTimer(); } +} - // To prevent from punish the player twice with critical + damage boost, just uncomment code from the if - if (monster->getHazardSystemDamageBoost() /* && !damage.critical*/) { - stage = points * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_DAMAGE_MULTIPLIER)); - if (stage != 0) { - damage.extension = true; - damage.exString = "(Hazard)"; - damage.primary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * stage) / 10000)); - if (damage.secondary.value != 0) { - damage.secondary.value += static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * stage) / 10000)); - } - } +void Player::setSlotBossId(uint8_t slotId, uint32_t bossId) { + if (slotId == 1) { + bossIdSlotOne = bossId; + } else { + bossIdSlotTwo = bossId; + } + if (client) { + client->parseSendBosstiarySlots(); } } -void Player::parseAttackDealtHazardSystem(CombatDamage &damage, std::shared_ptr<Monster> monster) { - if (!g_configManager().getBoolean(TOGGLE_HAZARDSYSTEM)) { - return; +uint32_t Player::getSlotBossId(uint8_t slotId) const { + if (slotId == 1) { + return bossIdSlotOne; + } else { + return bossIdSlotTwo; } +} - if (!monster || !monster->getHazard()) { - return; - } +void Player::addRemoveTime() { + bossRemoveTimes = bossRemoveTimes + 1; +} - if (damage.primary.type == COMBAT_HEALING) { - return; - } +void Player::setRemoveBossTime(uint8_t newRemoveTimes) { + bossRemoveTimes = newRemoveTimes; +} - auto points = getHazardSystemPoints(); - if (m_party) { - for (const auto &partyMember : m_party->getMembers()) { - if (partyMember && partyMember->getHazardSystemPoints() < points) { - points = partyMember->getHazardSystemPoints(); - } - } +uint8_t Player::getRemoveTimes() const { + return bossRemoveTimes; +} - if (m_party->getLeader() && m_party->getLeader()->getHazardSystemPoints() < points) { - points = m_party->getLeader()->getHazardSystemPoints(); - } +void Player::sendMonsterPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos) const { + if (client) { + client->sendMonsterPodiumWindow(podium, position, itemId, stackpos); } +} - if (points == 0) { - return; +void Player::sendBosstiaryEntryChanged(uint32_t bossid) const { + if (client) { + client->sendBosstiaryEntryChanged(bossid); } +} - // Dodge chance - uint16_t stage; - if (monster->getHazardSystemDodge()) { - stage = points * g_configManager().getNumber(HAZARD_DODGE_MULTIPLIER); - auto chance = static_cast<uint16_t>(normal_random(1, 10000)); - if (chance <= stage) { - damage.primary.value = 0; - damage.secondary.value = 0; - return; - } - } - if (monster->getHazardSystemDefenseBoost()) { - stage = points * static_cast<uint16_t>(g_configManager().getNumber(HAZARD_DEFENSE_MULTIPLIER)); - if (stage != 0) { - damage.exString = fmt::format("(hazard -{}%)", stage / 100.); - damage.primary.value -= static_cast<int32_t>(std::ceil((static_cast<double>(damage.primary.value) * stage) / 10000)); - if (damage.secondary.value != 0) { - damage.secondary.value -= static_cast<int32_t>(std::ceil((static_cast<double>(damage.secondary.value) * stage) / 10000)); - } - return; - } +void Player::sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> &items) const { + if (client) { + client->sendInventoryImbuements(items); } } @@ -8102,13 +10265,13 @@ const std::unique_ptr<PlayerCyclopedia> &Player::cyclopedia() const { } void Player::sendLootMessage(const std::string &message) const { - auto party = getParty(); + const auto &party = getParty(); if (!party) { sendTextMessage(MESSAGE_LOOT, message); return; } - if (auto partyLeader = party->getLeader()) { + if (const auto &partyLeader = party->getLeader()) { partyLeader->sendTextMessage(MESSAGE_LOOT, message); } for (const auto &partyMember : party->getMembers()) { @@ -8120,20 +10283,20 @@ void Player::sendLootMessage(const std::string &message) const { std::shared_ptr<Container> Player::getLootPouch() { // Allow players with CM access or higher have the loot pouch anywhere - auto parentItem = getParent() ? getParent()->getItem() : nullptr; + const auto &parentItem = getParent() ? getParent()->getItem() : nullptr; if (isPlayerGroup() && parentItem && parentItem->getID() != ITEM_STORE_INBOX) { return nullptr; } - auto inventoryItems = getInventoryItemsFromId(ITEM_GOLD_POUCH); + const auto &inventoryItems = getInventoryItemsFromId(ITEM_GOLD_POUCH); if (inventoryItems.empty()) { return nullptr; } - auto containerItem = inventoryItems.front(); + const auto &containerItem = inventoryItems.front(); if (!containerItem) { return nullptr; } - auto container = containerItem->getContainer(); + const auto &container = containerItem->getContainer(); if (!container) { return nullptr; } @@ -8142,12 +10305,12 @@ std::shared_ptr<Container> Player::getLootPouch() { } std::shared_ptr<Container> Player::getStoreInbox() const { - auto thing = getThing(CONST_SLOT_STORE_INBOX); + const auto &thing = getThing(CONST_SLOT_STORE_INBOX); if (!thing) { return nullptr; } - auto storeInbox = thing->getContainer(); + const auto &storeInbox = thing->getContainer(); return storeInbox ? storeInbox : nullptr; } @@ -8162,7 +10325,11 @@ bool Player::hasPermittedConditionInPZ() const { }; bool hasPermittedCondition = false; - for (auto condition : allowedConditions) { + for (const auto &condition : allowedConditions) { + if (!condition) { + continue; + } + if (getCondition(condition)) { hasPermittedCondition = true; break; @@ -8174,7 +10341,7 @@ bool Player::hasPermittedConditionInPZ() const { uint16_t Player::getDodgeChance() const { uint16_t chance = 0; - if (auto playerArmor = getInventoryItem(CONST_SLOT_ARMOR); + if (const auto &playerArmor = getInventoryItem(CONST_SLOT_ARMOR); playerArmor != nullptr && playerArmor->getTier()) { chance += static_cast<uint16_t>(playerArmor->getDodgeChance() * 100); } @@ -8184,6 +10351,50 @@ uint16_t Player::getDodgeChance() const { return chance; } +uint8_t Player::isRandomMounted() const { + return randomMount; +} + +void Player::setRandomMount(uint8_t isMountRandomized) { + randomMount = isMountRandomized; +} + +void Player::sendFYIBox(const std::string &message) const { + if (client) { + client->sendFYIBox(message); + } +} + +void Player::BestiarysendCharms() const { + if (client) { + client->BestiarysendCharms(); + } +} + +void Player::addBestiaryKillCount(uint16_t raceid, uint32_t amount) { + const uint32_t oldCount = getBestiaryKillCount(raceid); + const uint32_t key = STORAGEVALUE_BESTIARYKILLCOUNT + raceid; + addStorageValue(key, static_cast<int32_t>(oldCount + amount), true); +} + +uint32_t Player::getBestiaryKillCount(uint16_t raceid) const { + const uint32_t key = STORAGEVALUE_BESTIARYKILLCOUNT + raceid; + const auto value = getStorageValue(key); + return value > 0 ? static_cast<uint32_t>(value) : 0; +} + +void Player::setGUID(uint32_t newGuid) { + this->guid = newGuid; +} + +uint32_t Player::getGUID() const { + return guid; +} + +bool Player::canSeeInvisibility() const { + return hasFlag(PlayerFlags_t::CanSenseInvisibility) || group->access; +} + void Player::checkAndShowBlessingMessage() { auto adventurerBlessingLevel = g_configManager().getNumber(ADVENTURERSBLESSING_LEVEL); auto willNotLoseBless = getLevel() < adventurerBlessingLevel && getVocationId() > VOCATION_NONE; @@ -8222,7 +10433,7 @@ bool Player::canSpeakWithHireling(uint8_t speechbubble) { } uint16_t Player::getPlayerVocationEnum() const { - int cipTibiaId = getVocation()->getClientId(); + const int cipTibiaId = getVocation()->getClientId(); if (cipTibiaId == 1 || cipTibiaId == 11) { return Vocation_t::VOCATION_KNIGHT_CIP; // Knight } else if (cipTibiaId == 2 || cipTibiaId == 12) { diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index cd69cec99a0..6ab3be4ca7a 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -9,37 +9,13 @@ #pragma once -#include "items/containers/container.hpp" #include "creatures/creature.hpp" -#include "items/cylinder.hpp" -#include "declarations.hpp" -#include "items/containers/depot/depotchest.hpp" -#include "items/containers/depot/depotlocker.hpp" -#include "grouping/familiars.hpp" #include "enums/forge_conversion.hpp" -#include "grouping/groups.hpp" -#include "grouping/guild.hpp" -#include "imbuements/imbuements.hpp" -#include "items/containers/inbox/inbox.hpp" -#include "io/ioguild.hpp" -#include "io/ioprey.hpp" -#include "creatures/appearance/mounts/mounts.hpp" -#include "creatures/appearance/outfit/outfit.hpp" -#include "grouping/party.hpp" -#include "server/network/protocol/protocolgame.hpp" -#include "items/containers/rewards/reward.hpp" -#include "items/containers/rewards/rewardchest.hpp" -#include "map/town.hpp" -#include "vocations/vocation.hpp" -#include "creatures/npcs/npc.hpp" #include "game/bank/bank.hpp" -#include "enums/object_category.hpp" -#include "enums/player_cyclopedia.hpp" -#include "enums/player_icons.hpp" -#include "creatures/players/cyclopedia/player_badge.hpp" -#include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "creatures/players/cyclopedia/player_title.hpp" -#include "creatures/players/vip/player_vip.hpp" +#include "grouping/guild.hpp" +#include "items/cylinder.hpp" +#include "game/movement/position.hpp" +#include "creatures/creatures_definitions.hpp" class House; class NetworkMessage; @@ -47,7 +23,6 @@ class Weapon; class ProtocolGame; class Party; class Task; -class Bed; class Guild; class Imbuement; class PreySlot; @@ -61,12 +36,45 @@ class PlayerTitle; class PlayerVIP; class Spectators; class Account; +class RewardChest; +class Cylinder; +class Town; +class Reward; +class DepotChest; +class DepotLocker; +class Inbox; +class Vocation; +class Container; +class KV; +class BedItem; +class Npc; struct ModalWindow; struct Achievement; -struct Badge; -struct Title; struct VIPGroup; +struct Mount; +struct OutfitEntry; +struct Outfit; +struct FamiliarEntry; +struct Familiar; +struct Group; +struct Outfit_t; +struct TextMessage; +struct HighscoreCharacter; + +enum class PlayerIcon : uint8_t; +enum class IconBakragore : uint8_t; +enum ObjectCategory_t : uint8_t; +enum PreySlot_t : uint8_t; +enum SpeakClasses : uint8_t; +enum ChannelEvent_t : uint8_t; +enum SquareColor_t : uint8_t; + +using GuildWarVector = std::vector<uint32_t>; +using StashContainerList = std::vector<std::pair<std::shared_ptr<Item>, uint32_t>>; +using ItemVector = std::vector<std::shared_ptr<Item>>; +using UsersMap = std::map<uint32_t, std::shared_ptr<Player>>; +using InvitedMap = std::map<uint32_t, std::shared_ptr<Player>>; struct ForgeHistory { ForgeAction_t actionType = ForgeAction_t::FUSION; @@ -123,8 +131,8 @@ class Player final : public Creature, public Cylinder, public Bankable { const std::shared_ptr<Player> &player; }; - explicit Player(ProtocolGame_ptr p); - ~Player(); + explicit Player(std::shared_ptr<ProtocolGame> p); + ~Player() override; // non-copyable Player(const Player &) = delete; @@ -137,7 +145,7 @@ class Player final : public Creature, public Cylinder, public Bankable { return static_self_cast<Player>(); } - static std::shared_ptr<Task> createPlayerTask(uint32_t delay, std::function<void(void)> f, std::string context); + static std::shared_ptr<Task> createPlayerTask(uint32_t delay, std::function<void(void)> f, const std::string &context); void setID() override; @@ -180,139 +188,69 @@ class Player final : public Creature, public Cylinder, public Bankable { bool toggleMount(bool mount); bool tameMount(uint8_t mountId); bool untameMount(uint8_t mountId); - bool hasMount(const std::shared_ptr<Mount> mount) const; + bool hasMount(const std::shared_ptr<Mount> &mount) const; bool hasAnyMount() const; uint8_t getRandomMountId() const; void dismount(); uint16_t getDodgeChance() const; - uint8_t isRandomMounted() const { - return randomMount; - } - void setRandomMount(uint8_t isMountRandomized) { - randomMount = isMountRandomized; - } + uint8_t isRandomMounted() const; + void setRandomMount(uint8_t isMountRandomized); - void sendFYIBox(const std::string &message) { - if (client) { - client->sendFYIBox(message); - } - } + void sendFYIBox(const std::string &message) const; - void BestiarysendCharms() { - if (client) { - client->BestiarysendCharms(); - } - } - void addBestiaryKillCount(uint16_t raceid, uint32_t amount) { - uint32_t oldCount = getBestiaryKillCount(raceid); - uint32_t key = STORAGEVALUE_BESTIARYKILLCOUNT + raceid; - addStorageValue(key, static_cast<int32_t>(oldCount + amount), true); - } - uint32_t getBestiaryKillCount(uint16_t raceid) const { - uint32_t key = STORAGEVALUE_BESTIARYKILLCOUNT + raceid; - auto value = getStorageValue(key); - return value > 0 ? static_cast<uint32_t>(value) : 0; - } + void BestiarysendCharms() const; + void addBestiaryKillCount(uint16_t raceid, uint32_t amount); + uint32_t getBestiaryKillCount(uint16_t raceid) const; - void setGUID(uint32_t newGuid) { - this->guid = newGuid; - } - uint32_t getGUID() const { - return guid; - } - bool canSeeInvisibility() const override { - return hasFlag(PlayerFlags_t::CanSenseInvisibility) || group->access; - } + void setGUID(uint32_t newGuid); + uint32_t getGUID() const; + bool canSeeInvisibility() const override; - void setDailyReward(uint8_t reward) { - this->isDailyReward = reward; - } + void setDailyReward(uint8_t reward); void removeList() override; void addList() override; void removePlayer(bool displayEffect, bool forced = true); - static uint64_t getExpForLevel(const uint32_t level) { - return (((level - 6ULL) * level + 17ULL) * level - 12ULL) / 6ULL * 100ULL; - } + static uint64_t getExpForLevel(const uint32_t level); - uint16_t getStaminaMinutes() const { - return staminaMinutes; - } + uint16_t getStaminaMinutes() const; - void sendItemsPrice() { - if (client) { - client->sendItemsPrice(); - } - } + void sendItemsPrice() const; - void sendForgingData() const { - if (client) { - client->sendForgingData(); - } - } + void sendForgingData() const; bool addOfflineTrainingTries(skills_t skill, uint64_t tries); - void addOfflineTrainingTime(int32_t addTime) { - offlineTrainingTime = std::min<int32_t>(12 * 3600 * 1000, offlineTrainingTime + addTime); - } - void removeOfflineTrainingTime(int32_t removeTime) { - offlineTrainingTime = std::max<int32_t>(0, offlineTrainingTime - removeTime); - } - int32_t getOfflineTrainingTime() const { - return offlineTrainingTime; - } + void addOfflineTrainingTime(int32_t addTime); + void removeOfflineTrainingTime(int32_t removeTime); + int32_t getOfflineTrainingTime() const; - int8_t getOfflineTrainingSkill() const { - return offlineTrainingSkill; - } - void setOfflineTrainingSkill(int8_t skill) { - offlineTrainingSkill = skill; - } + int8_t getOfflineTrainingSkill() const; + void setOfflineTrainingSkill(int8_t skill); - uint64_t getBankBalance() const override { - return bankBalance; - } - void setBankBalance(uint64_t balance) override { - bankBalance = balance; - } + uint64_t getBankBalance() const override; + void setBankBalance(uint64_t balance) override; - [[nodiscard]] std::shared_ptr<Guild> getGuild() const { - return guild; - } - void setGuild(const std::shared_ptr<Guild> guild); + [[nodiscard]] std::shared_ptr<Guild> getGuild() const; + void setGuild(const std::shared_ptr<Guild> &guild); - [[nodiscard]] GuildRank_ptr getGuildRank() const { - return guildRank; - } - void setGuildRank(GuildRank_ptr newGuildRank) { - guildRank = newGuildRank; - } + [[nodiscard]] GuildRank_ptr getGuildRank() const; + void setGuildRank(GuildRank_ptr newGuildRank); - bool isGuildMate(std::shared_ptr<Player> player) const; + bool isGuildMate(const std::shared_ptr<Player> &player) const; - [[nodiscard]] const std::string &getGuildNick() const { - return guildNick; - } - void setGuildNick(std::string nick) { - guildNick = nick; - } + [[nodiscard]] const std::string &getGuildNick() const; + void setGuildNick(std::string nick); - bool isInWar(std::shared_ptr<Player> player) const; + bool isInWar(const std::shared_ptr<Player> &player) const; bool isInWarList(uint32_t guild_id) const; - void setLastWalkthroughAttempt(int64_t walkthroughAttempt) { - lastWalkthroughAttempt = walkthroughAttempt; - } - void setLastWalkthroughPosition(Position walkthroughPosition) { - lastWalkthroughPosition = walkthroughPosition; - } + void setLastWalkthroughAttempt(int64_t walkthroughAttempt); + void setLastWalkthroughPosition(Position walkthroughPosition); - std::shared_ptr<Inbox> getInbox() const { - return inbox; - } + std::shared_ptr<Inbox> getInbox() const; std::unordered_set<PlayerIcon> getClientIcons(); @@ -320,220 +258,126 @@ class Player final : public Creature, public Cylinder, public Bankable { return guildWarVector; } - const std::unordered_set<std::shared_ptr<MonsterType>> &getCyclopediaMonsterTrackerSet(bool isBoss) const { - return isBoss ? m_bosstiaryMonsterTracker : m_bestiaryMonsterTracker; - } + const std::unordered_set<std::shared_ptr<MonsterType>> &getCyclopediaMonsterTrackerSet(bool isBoss) const; - void addMonsterToCyclopediaTrackerList(const std::shared_ptr<MonsterType> mtype, bool isBoss, bool reloadClient = false); + void addMonsterToCyclopediaTrackerList(const std::shared_ptr<MonsterType> &mtype, bool isBoss, bool reloadClient = false); - void removeMonsterFromCyclopediaTrackerList(std::shared_ptr<MonsterType> mtype, bool isBoss, bool reloadClient = false); + void removeMonsterFromCyclopediaTrackerList(const std::shared_ptr<MonsterType> &mtype, bool isBoss, bool reloadClient = false); - void sendBestiaryEntryChanged(uint16_t raceid) { - if (client) { - client->sendBestiaryEntryChanged(raceid); - } - } + void sendBestiaryEntryChanged(uint16_t raceid) const; - void refreshCyclopediaMonsterTracker(bool isBoss = false) { + void refreshCyclopediaMonsterTracker(bool isBoss = false) const { refreshCyclopediaMonsterTracker(getCyclopediaMonsterTrackerSet(isBoss), isBoss); } - void refreshCyclopediaMonsterTracker(const std::unordered_set<std::shared_ptr<MonsterType>> &trackerList, bool isBoss) const { - if (client) { - client->refreshCyclopediaMonsterTracker(trackerList, isBoss); - } - } + void refreshCyclopediaMonsterTracker(const std::unordered_set<std::shared_ptr<MonsterType>> &trackerList, bool isBoss) const; bool isBossOnBosstiaryTracker(const std::shared_ptr<MonsterType> &monsterType) const; - std::shared_ptr<Vocation> getVocation() const { - return vocation; - } - - OperatingSystem_t getOperatingSystem() const { - return operatingSystem; - } - void setOperatingSystem(OperatingSystem_t clientos) { - operatingSystem = clientos; - } + std::shared_ptr<Vocation> getVocation() const; - bool isOldProtocol() { - return client && client->oldProtocol; - } + OperatingSystem_t getOperatingSystem() const; + void setOperatingSystem(OperatingSystem_t clientos); - uint32_t getProtocolVersion() const { - if (!client) { - return 0; - } + bool isOldProtocol() const; - return client->getVersion(); - } + uint32_t getProtocolVersion() const; - bool hasSecureMode() const { - return secureMode; - } + bool hasSecureMode() const; - void setParty(std::shared_ptr<Party> newParty) { - m_party = newParty; - } - std::shared_ptr<Party> getParty() const { - return m_party; - } + void setParty(std::shared_ptr<Party> newParty); + std::shared_ptr<Party> getParty() const; int32_t getCleavePercent(bool useCharges = false) const; - void setCleavePercent(int32_t value) { - cleavePercent = std::max(0, cleavePercent + value); - } + void setCleavePercent(int32_t value); int32_t getPerfectShotDamage(uint8_t range, bool useCharges = false) const; - void setPerfectShotDamage(uint8_t range, int32_t damage) { - int32_t actualDamage = getPerfectShotDamage(range); - bool aboveZero = (actualDamage != 0); - actualDamage += damage; - if (actualDamage == 0 && aboveZero) { - perfectShot.erase(range); - } else { - perfectShot[range] = actualDamage; - } - } + void setPerfectShotDamage(uint8_t range, int32_t damage); int32_t getSpecializedMagicLevel(CombatType_t combat, bool useCharges = false) const; - void setSpecializedMagicLevel(CombatType_t combat, int32_t value) { - specializedMagicLevel[combatTypeToIndex(combat)] = std::max(0, specializedMagicLevel[combatTypeToIndex(combat)] + value); - } + void setSpecializedMagicLevel(CombatType_t combat, int32_t value); int32_t getMagicShieldCapacityFlat(bool useCharges = false) const; - void setMagicShieldCapacityFlat(int32_t value) { - magicShieldCapacityFlat += value; - } + void setMagicShieldCapacityFlat(int32_t value); int32_t getMagicShieldCapacityPercent(bool useCharges = false) const; - void setMagicShieldCapacityPercent(int32_t value) { - magicShieldCapacityPercent += value; - } + void setMagicShieldCapacityPercent(int32_t value); double_t getReflectPercent(CombatType_t combat, bool useCharges = false) const override; int32_t getReflectFlat(CombatType_t combat, bool useCharges = false) const override; - PartyShields_t getPartyShield(std::shared_ptr<Player> player); - bool isInviting(std::shared_ptr<Player> player) const; - bool isPartner(std::shared_ptr<Player> player) const; - void sendPlayerPartyIcons(std::shared_ptr<Player> player); - bool addPartyInvitation(std::shared_ptr<Party> party); - void removePartyInvitation(std::shared_ptr<Party> party); + PartyShields_t getPartyShield(const std::shared_ptr<Player> &player); + bool isInviting(const std::shared_ptr<Player> &player) const; + bool isPartner(const std::shared_ptr<Player> &player) const; + void sendPlayerPartyIcons(const std::shared_ptr<Player> &player) const; + bool addPartyInvitation(const std::shared_ptr<Party> &party); + void removePartyInvitation(const std::shared_ptr<Party> &party); void clearPartyInvitations(); - void sendUnjustifiedPoints(); - - GuildEmblems_t getGuildEmblem(std::shared_ptr<Player> player) const; - - uint64_t getSpentMana() const { - return manaSpent; - } + void sendUnjustifiedPoints() const; - bool hasFlag(PlayerFlags_t flag) const { - return group->flags[static_cast<std::size_t>(flag)]; - } + GuildEmblems_t getGuildEmblem(const std::shared_ptr<Player> &player) const; - void setFlag(PlayerFlags_t flag) const { - group->flags[static_cast<std::size_t>(flag)] = true; - } + uint64_t getSpentMana() const; - void removeFlag(PlayerFlags_t flag) const { - group->flags[static_cast<std::size_t>(flag)] = false; - } + bool hasFlag(PlayerFlags_t flag) const; - std::shared_ptr<BedItem> getBedItem() { - return bedItem; - } - void setBedItem(std::shared_ptr<BedItem> b) { - bedItem = b; - } + void setFlag(PlayerFlags_t flag) const; - bool hasImbuingItem() { - return imbuingItem != nullptr; - } - void setImbuingItem(std::shared_ptr<Item> item); + void removeFlag(PlayerFlags_t flag) const; - void addBlessing(uint8_t index, uint8_t count) { - if (blessings[index - 1] == 255) { - return; - } + std::shared_ptr<BedItem> getBedItem(); + void setBedItem(std::shared_ptr<BedItem> b); - blessings[index - 1] += count; - } - void removeBlessing(uint8_t index, uint8_t count) { - if (blessings[index - 1] == 0) { - return; - } + bool hasImbuingItem() const; + void setImbuingItem(const std::shared_ptr<Item> &item); - blessings[index - 1] -= count; - } - bool hasBlessing(uint8_t index) const { - return blessings[index - 1] != 0; - } + void addBlessing(uint8_t index, uint8_t count); + void removeBlessing(uint8_t index, uint8_t count); + bool hasBlessing(uint8_t index) const; - uint8_t getBlessingCount(uint8_t index, bool storeCount = false) const { - if (!storeCount) { - if (index > 0 && index <= blessings.size()) { - return blessings[index - 1]; - } else { - g_logger().error("[{}] - index outside range 0-10.", __FUNCTION__); - return 0; - } - } - auto amount = kv()->scoped("summary")->scoped("blessings")->scoped(fmt::format("{}", index))->get("amount"); - return amount ? static_cast<uint8_t>(amount->getNumber()) : 0; - } + uint8_t getBlessingCount(uint8_t index, bool storeCount = false) const; std::string getBlessingsName() const; bool isOffline() const { return (getID() == 0); } - void disconnect() { - if (client) { - client->disconnect(); - } - } + void disconnect() const; - uint32_t getIP() const { - return client ? client->getIP() : 0; - } + uint32_t getIP() const; bool isDisconnected() const { return getIP() == 0; } - void addContainer(uint8_t cid, std::shared_ptr<Container> container); + void addContainer(uint8_t cid, const std::shared_ptr<Container> &container); void closeContainer(uint8_t cid); void setContainerIndex(uint8_t cid, uint16_t index); std::shared_ptr<Container> getContainerByID(uint8_t cid); - int8_t getContainerID(std::shared_ptr<Container> container) const; + int8_t getContainerID(const std::shared_ptr<Container> &container) const; uint16_t getContainerIndex(uint8_t cid) const; bool canOpenCorpse(uint32_t ownerId) const; - void addStorageValue(const uint32_t key, const int32_t value, const bool isLogin = false); - int32_t getStorageValue(const uint32_t key) const; + void addStorageValue(uint32_t key, int32_t value, bool isLogin = false); + int32_t getStorageValue(uint32_t key) const; int32_t getStorageValueByName(const std::string &storageName) const; - void addStorageValueByName(const std::string &storageName, const int32_t value, const bool isLogin = false); + void addStorageValueByName(const std::string &storageName, int32_t value, bool isLogin = false); - std::shared_ptr<KV> kv() const { - return g_kv().scoped("player")->scoped(fmt::format("{}", getGUID())); - } + std::shared_ptr<KV> kv() const; void genReservedStorageRange(); void setGroup(std::shared_ptr<Group> newGroup) { - group = newGroup; + group = std::move(newGroup); } std::shared_ptr<Group> getGroup() const { return group; @@ -545,23 +389,7 @@ class Player final : public Creature, public Cylinder, public Bankable { bool isInMarket() const { return inMarket; } - void setSpecialMenuAvailable(bool supplyStashBool, bool marketMenuBool, bool depotSearchBool) { - // Closing depot search when player have special container disabled and it's still open. - if (isDepotSearchOpen() && !depotSearchBool && depotSearch) { - depotSearchOnItem = { 0, 0 }; - sendCloseDepotSearch(); - } - - // Menu option 'stow, stow container ...' - // Menu option 'show in market' - // Menu option to open depot search - supplyStash = supplyStashBool; - marketMenu = marketMenuBool; - depotSearch = depotSearchBool; - if (client) { - client->sendSpecialContainersAvailable(); - } - } + void setSpecialMenuAvailable(bool supplyStashBool, bool marketMenuBool, bool depotSearchBool); bool isDepotSearchOpen() const { return depotSearchOnItem.first != 0; } @@ -574,13 +402,13 @@ class Player final : public Creature, public Cylinder, public Bankable { bool isDepotSearchAvailable() const { return depotSearch; } - bool isSupplyStashMenuAvailable() { + bool isSupplyStashMenuAvailable() const { return supplyStash; } - bool isMarketMenuAvailable() { + bool isMarketMenuAvailable() const { return marketMenu; } - bool isExerciseTraining() { + bool isExerciseTraining() const { return exerciseTraining; } void setExerciseTraining(bool isTraining) { @@ -629,9 +457,7 @@ class Player final : public Creature, public Cylinder, public Bankable { uint32_t getPremiumDays() const; time_t getPremiumLastDay() const; - bool isVip() const { - return g_configManager().getBoolean(VIP_SYSTEM_ENABLED) && (getPremiumDays() > 0 || getPremiumLastDay() > getTimeNow()); - } + bool isVip() const; void setTibiaCoins(int32_t v); void setTransferableTibiaCoins(int32_t v); @@ -639,9 +465,7 @@ class Player final : public Creature, public Cylinder, public Bankable { uint16_t getHelpers() const; bool setVocation(uint16_t vocId); - uint16_t getVocationId() const { - return vocation->getId(); - } + uint16_t getVocationId() const; PlayerSex_t getSex() const { return sex; @@ -649,21 +473,11 @@ class Player final : public Creature, public Cylinder, public Bankable { PlayerPronoun_t getPronoun() const { return pronoun; } - std::string getObjectPronoun() const { - return getPlayerObjectPronoun(pronoun, sex, name); - } - std::string getSubjectPronoun() const { - return getPlayerSubjectPronoun(pronoun, sex, name); - } - std::string getPossessivePronoun() const { - return getPlayerPossessivePronoun(pronoun, sex, name); - } - std::string getReflexivePronoun() const { - return getPlayerReflexivePronoun(pronoun, sex, name); - } - std::string getSubjectVerb(bool past = false) const { - return getVerbForPronoun(pronoun, past); - } + std::string getObjectPronoun() const; + std::string getSubjectPronoun() const; + std::string getPossessivePronoun() const; + std::string getReflexivePronoun() const; + std::string getSubjectVerb(bool past = false) const; void setSex(PlayerSex_t); void setPronoun(PlayerPronoun_t); uint64_t getExperience() const { @@ -681,20 +495,9 @@ class Player final : public Creature, public Cylinder, public Bankable { const Position &getLoginPosition() const { return loginPosition; } - const Position &getTemplePosition() const { - if (!town) { - static auto emptyPosition = Position(); - return emptyPosition; - } - - return town->getTemplePosition(); - } - std::shared_ptr<Town> getTown() const { - return town; - } - void setTown(const std::shared_ptr<Town> &newTown) { - this->town = newTown; - } + const Position &getTemplePosition() const; + std::shared_ptr<Town> getTown() const; + void setTown(const std::shared_ptr<Town> &newTown); void clearModalWindows(); bool hasModalWindowOpen(uint32_t modalWindowId) const; @@ -705,7 +508,7 @@ class Player final : public Creature, public Cylinder, public Bankable { void addMessageBuffer(); void removeMessageBuffer(); - bool removeItemOfType(uint16_t itemId, uint32_t itemAmount, int32_t subType, bool ignoreEquipped = false); + bool removeItemOfType(uint16_t itemId, uint32_t itemAmount, int32_t subType, bool ignoreEquipped = false) const; /** * @param itemAmount is uint32_t because stash item is uint32_t max */ @@ -715,83 +518,28 @@ class Player final : public Creature, public Cylinder, public Bankable { */ bool removeItemCountById(uint16_t itemId, uint32_t itemAmount, bool removeFromStash = true); - void addItemOnStash(uint16_t itemId, uint32_t amount) { - auto it = stashItems.find(itemId); - if (it != stashItems.end()) { - stashItems[itemId] += amount; - return; - } - - stashItems[itemId] = amount; - } - uint32_t getStashItemCount(uint16_t itemId) const { - auto it = stashItems.find(itemId); - if (it != stashItems.end()) { - return it->second; - } - return 0; - } - bool withdrawItem(uint16_t itemId, uint32_t amount) { - auto it = stashItems.find(itemId); - if (it != stashItems.end()) { - if (it->second > amount) { - stashItems[itemId] -= amount; - } else if (it->second == amount) { - stashItems.erase(itemId); - } else { - return false; - } - return true; - } - return false; - } - StashItemList getStashItems() const { - return stashItems; - } + void addItemOnStash(uint16_t itemId, uint32_t amount); + uint32_t getStashItemCount(uint16_t itemId) const; + bool withdrawItem(uint16_t itemId, uint32_t amount); + StashItemList getStashItems() const; - uint32_t getBaseCapacity() const { - if (hasFlag(PlayerFlags_t::CannotPickupItem)) { - return 0; - } else if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { - return std::numeric_limits<uint32_t>::max(); - } - return capacity; - } + uint32_t getBaseCapacity() const; uint32_t getCapacity() const; - uint32_t getBonusCapacity() const { - if (hasFlag(PlayerFlags_t::CannotPickupItem) || hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { - return std::numeric_limits<uint32_t>::max(); - } - return bonusCapacity; - } + uint32_t getBonusCapacity() const; - uint32_t getFreeCapacity() const { - if (hasFlag(PlayerFlags_t::CannotPickupItem)) { - return 0; - } else if (hasFlag(PlayerFlags_t::HasInfiniteCapacity)) { - return std::numeric_limits<uint32_t>::max(); - } else { - return std::max<int32_t>(0, getCapacity() - inventoryWeight); - } - } + uint32_t getFreeCapacity() const; int32_t getMaxHealth() const override; uint32_t getMaxMana() const override; std::shared_ptr<Item> getInventoryItem(Slots_t slot) const; - bool isItemAbilityEnabled(Slots_t slot) const { - return inventoryAbilities[slot]; - } - void setItemAbility(Slots_t slot, bool enabled) { - inventoryAbilities[slot] = enabled; - } + bool isItemAbilityEnabled(Slots_t slot) const; + void setItemAbility(Slots_t slot, bool enabled); - void setVarSkill(skills_t skill, int32_t modifier) { - varSkills[skill] += modifier; - } + void setVarSkill(skills_t skill, int32_t modifier); void setVarStats(stats_t stat, int32_t modifier); int32_t getDefaultStats(stats_t stat) const; @@ -799,57 +547,45 @@ class Player final : public Creature, public Cylinder, public Bankable { void addConditionSuppressions(const std::array<ConditionType_t, ConditionType_t::CONDITION_COUNT> &addCondition); void removeConditionSuppressions(); - std::shared_ptr<Reward> getReward(const uint64_t rewardId, const bool autoCreate); + std::shared_ptr<Reward> getReward(uint64_t rewardId, bool autoCreate); void removeReward(uint64_t rewardId); void getRewardList(std::vector<uint64_t> &rewards) const; std::shared_ptr<RewardChest> getRewardChest(); - std::vector<std::shared_ptr<Item>> getRewardsFromContainer(std::shared_ptr<Container> container) const; + std::vector<std::shared_ptr<Item>> getRewardsFromContainer(const std::shared_ptr<Container> &container) const; std::shared_ptr<DepotChest> getDepotChest(uint32_t depotId, bool autoCreate); std::shared_ptr<DepotLocker> getDepotLocker(uint32_t depotId); void onReceiveMail(); bool isNearDepotBox(); - std::shared_ptr<Container> refreshManagedContainer(ObjectCategory_t category, std::shared_ptr<Container> container, bool isLootContainer, bool loading = false); + std::shared_ptr<Container> refreshManagedContainer(ObjectCategory_t category, const std::shared_ptr<Container> &container, bool isLootContainer, bool loading = false); std::shared_ptr<Container> getManagedContainer(ObjectCategory_t category, bool isLootContainer) const; - void setMainBackpackUnassigned(std::shared_ptr<Container> container); + void setMainBackpackUnassigned(const std::shared_ptr<Container> &container); bool canSee(const Position &pos) override; - bool canSeeCreature(std::shared_ptr<Creature> creature) const override; + bool canSeeCreature(const std::shared_ptr<Creature> &creature) const override; - bool canWalkthrough(std::shared_ptr<Creature> creature); - bool canWalkthroughEx(std::shared_ptr<Creature> creature); + bool canWalkthrough(const std::shared_ptr<Creature> &creature); + bool canWalkthroughEx(const std::shared_ptr<Creature> &creature) const; - RaceType_t getRace() const override { - return RACE_BLOOD; - } + RaceType_t getRace() const override; uint64_t getMoney() const; std::pair<uint64_t, uint64_t> getForgeSliversAndCores() const; // safe-trade functions - void setTradeState(TradeState_t state) { - tradeState = state; - } - TradeState_t getTradeState() const { - return tradeState; - } - std::shared_ptr<Item> getTradeItem() { - return tradeItem; - } + void setTradeState(TradeState_t state); + TradeState_t getTradeState() const; + std::shared_ptr<Item> getTradeItem(); // shop functions - void setShopOwner(std::shared_ptr<Npc> owner) { - shopOwner = owner; - } + void setShopOwner(std::shared_ptr<Npc> owner); - std::shared_ptr<Npc> getShopOwner() const { - return shopOwner; - } + std::shared_ptr<Npc> getShopOwner() const; // follow functions - bool setFollowCreature(std::shared_ptr<Creature> creature) override; + bool setFollowCreature(const std::shared_ptr<Creature> &creature) override; void goToFollowCreature() override; // follow events @@ -861,125 +597,74 @@ class Player final : public Creature, public Cylinder, public Bankable { void onWalkComplete() override; void stopWalk(); - bool openShopWindow(std::shared_ptr<Npc> npc, const std::vector<ShopBlock> &shopItems = {}); + bool openShopWindow(const std::shared_ptr<Npc> &npc, const std::vector<ShopBlock> &shopItems = {}); bool closeShopWindow(); - bool updateSaleShopList(std::shared_ptr<Item> item); + bool updateSaleShopList(const std::shared_ptr<Item> &item); bool hasShopItemForSale(uint16_t itemId, uint8_t subType) const; void setChaseMode(bool mode); - void setFightMode(FightMode_t mode) { - fightMode = mode; - } - void setSecureMode(bool mode) { - secureMode = mode; - } + void setFightMode(FightMode_t mode); + void setSecureMode(bool mode); - Faction_t getFaction() const override { - return faction; - } + Faction_t getFaction() const override; - void setFaction(Faction_t factionId) { - faction = factionId; - } + void setFaction(Faction_t factionId); // combat functions - bool setAttackedCreature(std::shared_ptr<Creature> creature) override; + bool setAttackedCreature(const std::shared_ptr<Creature> &creature) override; bool isImmune(CombatType_t type) const override; bool isImmune(ConditionType_t type) const override; bool hasShield() const; bool isAttackable() const override; - static bool lastHitIsPlayer(std::shared_ptr<Creature> lastHitCreature); + static bool lastHitIsPlayer(const std::shared_ptr<Creature> &lastHitCreature); // stash functions bool addItemFromStash(uint16_t itemId, uint32_t itemCount); - void stowItem(std::shared_ptr<Item> item, uint32_t count, bool allItems); + void stowItem(const std::shared_ptr<Item> &item, uint32_t count, bool allItems); void changeHealth(int32_t healthChange, bool sendHealthChange = true) override; void changeMana(int32_t manaChange) override; void changeSoul(int32_t soulChange); - bool isPzLocked() const { - return pzLocked; - } - BlockType_t blockHit(std::shared_ptr<Creature> attacker, CombatType_t combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false) override; + bool isPzLocked() const; + BlockType_t blockHit(const std::shared_ptr<Creature> &attacker, const CombatType_t &combatType, int32_t &damage, bool checkDefense = false, bool checkArmor = false, bool field = false) override; void doAttacking(uint32_t interval) override; - bool hasExtraSwing() override { - return lastAttack > 0 && !checkLastAttackWithin(getAttackSpeed()); - } + bool hasExtraSwing() override; uint16_t getSkillLevel(skills_t skill) const; uint16_t getLoyaltySkill(skills_t skill) const; - uint16_t getBaseSkill(uint8_t skill) const { - return skills[skill].level; - } - double_t getSkillPercent(skills_t skill) const { - return skills[skill].percent; - } - - bool getAddAttackSkill() const { - return addAttackSkillPoint; - } + uint16_t getBaseSkill(uint8_t skill) const; + double_t getSkillPercent(skills_t skill) const; - BlockType_t getLastAttackBlockType() const { - return lastAttackBlockType; - } + bool getAddAttackSkill() const; - uint64_t getLastConditionTime(ConditionType_t type) const { - if (!lastConditionTime.contains(static_cast<uint8_t>(type))) { - return 0; - } - return lastConditionTime.at(static_cast<uint8_t>(type)); - } + BlockType_t getLastAttackBlockType() const; - void updateLastConditionTime(ConditionType_t type) { - lastConditionTime[static_cast<uint8_t>(type)] = OTSYS_TIME(); - } + uint64_t getLastConditionTime(ConditionType_t type) const; - bool checkLastConditionTimeWithin(ConditionType_t type, uint32_t interval) const { - if (!lastConditionTime.contains(static_cast<uint8_t>(type))) { - return false; - } - auto last = lastConditionTime.at(static_cast<uint8_t>(type)); - return last > 0 && ((OTSYS_TIME() - last) < interval); - } + void updateLastConditionTime(ConditionType_t type); - uint64_t getLastAttack() const { - return lastAttack; - } + bool checkLastConditionTimeWithin(ConditionType_t type, uint32_t interval) const; - bool checkLastAttackWithin(uint32_t interval) const { - return lastAttack > 0 && ((OTSYS_TIME() - lastAttack) < interval); - } + uint64_t getLastAttack() const; - void updateLastAttack() { - if (lastAttack == 0) { - lastAttack = OTSYS_TIME() - getAttackSpeed() - 1; - return; - } - lastAttack = OTSYS_TIME(); - } + bool checkLastAttackWithin(uint32_t interval) const; - uint64_t getLastAggressiveAction() const { - return lastAggressiveAction; - } + void updateLastAttack(); - bool checkLastAggressiveActionWithin(uint32_t interval) const { - return lastAggressiveAction > 0 && ((OTSYS_TIME() - lastAggressiveAction) < interval); - } + uint64_t getLastAggressiveAction() const; - void updateLastAggressiveAction() { - lastAggressiveAction = OTSYS_TIME(); - } + bool checkLastAggressiveActionWithin(uint32_t interval) const; - std::unordered_set<std::string> getNPCSkips(); + void updateLastAggressiveAction(); std::shared_ptr<Item> getWeapon(Slots_t slot, bool ignoreAmmo) const; std::shared_ptr<Item> getWeapon(bool ignoreAmmo = false) const; WeaponType_t getWeaponType() const; - int32_t getWeaponSkill(std::shared_ptr<Item> item) const; + int32_t getWeaponSkill(const std::shared_ptr<Item> &item) const; void getShieldAndWeapon(std::shared_ptr<Item> &shield, std::shared_ptr<Item> &weapon) const; - void drainHealth(std::shared_ptr<Creature> attacker, int32_t damage) override; - void drainMana(std::shared_ptr<Creature> attacker, int32_t manaLoss) override; + void drainHealth(const std::shared_ptr<Creature> &attacker, int32_t damage) override; + void drainMana(const std::shared_ptr<Creature> &attacker, int32_t manaLoss) override; void addManaSpent(uint64_t amount); void addSkillAdvance(skills_t skill, uint64_t count); @@ -988,28 +673,27 @@ class Player final : public Creature, public Cylinder, public Bankable { float getAttackFactor() const override; float getDefenseFactor() const override; float getMitigation() const override; - double getMitigationMultiplier() const; void addInFightTicks(bool pzlock = false); - uint64_t getGainedExperience(std::shared_ptr<Creature> attacker) const override; + uint64_t getGainedExperience(const std::shared_ptr<Creature> &attacker) const override; // combat event functions void onAddCondition(ConditionType_t type) override; void onAddCombatCondition(ConditionType_t type) override; void onEndCondition(ConditionType_t type) override; - void onCombatRemoveCondition(std::shared_ptr<Condition> condition) override; - void onAttackedCreature(std::shared_ptr<Creature> target) override; + void onCombatRemoveCondition(const std::shared_ptr<Condition> &condition) override; + void onAttackedCreature(const std::shared_ptr<Creature> &target) override; void onAttacked() override; - void onAttackedCreatureDrainHealth(std::shared_ptr<Creature> target, int32_t points) override; - void onTargetCreatureGainHealth(std::shared_ptr<Creature> target, int32_t points) override; + void onAttackedCreatureDrainHealth(const std::shared_ptr<Creature> &target, int32_t points) override; + void onTargetCreatureGainHealth(const std::shared_ptr<Creature> &target, int32_t points) override; bool onKilledPlayer(const std::shared_ptr<Player> &target, bool lastHit) override; bool onKilledMonster(const std::shared_ptr<Monster> &target) override; - void onGainExperience(uint64_t gainExp, std::shared_ptr<Creature> target) override; - void onGainSharedExperience(uint64_t gainExp, std::shared_ptr<Creature> target); - void onAttackedCreatureBlockHit(BlockType_t blockType) override; + void onGainExperience(uint64_t gainExp, const std::shared_ptr<Creature> &target) override; + void onGainSharedExperience(uint64_t gainExp, const std::shared_ptr<Creature> &target); + void onAttackedCreatureBlockHit(const BlockType_t &blockType) override; void onBlockHit() override; - void onTakeDamage(std::shared_ptr<Creature> attacker, int32_t damage) override; + void onTakeDamage(const std::shared_ptr<Creature> &attacker, int32_t damage) override; void onChangeZone(ZoneType_t zone) override; void onAttackedCreatureChangeZone(ZoneType_t zone) override; void onIdleStatus() override; @@ -1018,29 +702,17 @@ class Player final : public Creature, public Cylinder, public Bankable { LightInfo getCreatureLight() const override; Skulls_t getSkull() const override; - Skulls_t getSkullClient(std::shared_ptr<Creature> creature) override; - int64_t getSkullTicks() const { - return skullTicks; - } - void setSkullTicks(int64_t ticks) { - skullTicks = ticks; - } + Skulls_t getSkullClient(const std::shared_ptr<Creature> &creature) override; + int64_t getSkullTicks() const; + void setSkullTicks(int64_t ticks); - bool hasAttacked(std::shared_ptr<Player> attacked) const; - void addAttacked(std::shared_ptr<Player> attacked); - void removeAttacked(std::shared_ptr<Player> attacked); + bool hasAttacked(const std::shared_ptr<Player> &attacked) const; + void addAttacked(const std::shared_ptr<Player> &attacked); + void removeAttacked(const std::shared_ptr<Player> &attacked); void clearAttacked(); - void addUnjustifiedDead(std::shared_ptr<Player> attacked); - void sendCreatureEmblem(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendCreatureEmblem(creature); - } - } - void sendCreatureSkull(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendCreatureSkull(creature); - } - } + void addUnjustifiedDead(const std::shared_ptr<Player> &attacked); + void sendCreatureEmblem(const std::shared_ptr<Creature> &creature) const; + void sendCreatureSkull(const std::shared_ptr<Creature> &creature) const; void checkSkullTicks(int64_t ticks); bool canWear(uint16_t lookType, uint8_t addons) const; @@ -1053,277 +725,81 @@ class Player final : public Creature, public Cylinder, public Bankable { void addFamiliar(uint16_t lookType); bool removeFamiliar(uint16_t lookType); bool getFamiliar(const std::shared_ptr<Familiar> &familiar) const; - void setFamiliarLooktype(uint16_t familiarLooktype) { - this->defaultOutfit.lookFamiliarsType = familiarLooktype; - } + void setFamiliarLooktype(uint16_t familiarLooktype); bool canLogout(); - bool hasKilled(std::shared_ptr<Player> player) const; + bool hasKilled(const std::shared_ptr<Player> &player) const; size_t getMaxDepotItems() const; // tile // send methods - void sendAddTileItem(std::shared_ptr<Tile> itemTile, const Position &pos, std::shared_ptr<Item> item) { - if (client) { - int32_t stackpos = itemTile->getStackposOfItem(static_self_cast<Player>(), item); - if (stackpos != -1) { - client->sendAddTileItem(pos, stackpos, item); - } - } - } - void sendUpdateTileItem(std::shared_ptr<Tile> updateTile, const Position &pos, std::shared_ptr<Item> item) { - if (client) { - int32_t stackpos = updateTile->getStackposOfItem(static_self_cast<Player>(), item); - if (stackpos != -1) { - client->sendUpdateTileItem(pos, stackpos, item); - } - } - } - void sendRemoveTileThing(const Position &pos, int32_t stackpos) { - if (stackpos != -1 && client) { - client->sendRemoveTileThing(pos, stackpos); - } - } - void sendUpdateTileCreature(const std::shared_ptr<Creature> creature) { - if (client) { - client->sendUpdateTileCreature(creature->getPosition(), creature->getTile()->getClientIndexOfCreature(static_self_cast<Player>(), creature), creature); - } - } - void sendUpdateTile(std::shared_ptr<Tile> updateTile, const Position &pos) { - if (client) { - client->sendUpdateTile(updateTile, pos); - } - } - - void sendChannelMessage(const std::string &author, const std::string &text, SpeakClasses type, uint16_t channel) { - if (client) { - client->sendChannelMessage(author, text, type, channel); - } - } - void sendChannelEvent(uint16_t channelId, const std::string &playerName, ChannelEvent_t channelEvent) { - if (client) { - client->sendChannelEvent(channelId, playerName, channelEvent); - } - } - void sendCreatureAppear(std::shared_ptr<Creature> creature, const Position &pos, bool isLogin) { - if (!creature) { - return; - } - - auto tile = creature->getTile(); - if (!tile) { - return; - } - - if (client) { - client->sendAddCreature(creature, pos, tile->getStackposOfCreature(static_self_cast<Player>(), creature), isLogin); - } - } - void sendCreatureMove(std::shared_ptr<Creature> creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport) { - if (client) { - client->sendMoveCreature(creature, newPos, newStackPos, oldPos, oldStackPos, teleport); - } - } - void sendCreatureTurn(std::shared_ptr<Creature> creature) { - if (!creature) { - return; - } - - auto tile = creature->getTile(); - if (!tile) { - return; - } - - if (client && canSeeCreature(creature)) { - int32_t stackpos = tile->getStackposOfCreature(static_self_cast<Player>(), creature); - if (stackpos != -1) { - client->sendCreatureTurn(creature, stackpos); - } - } - } - void sendCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, const Position* pos = nullptr) { - if (client) { - client->sendCreatureSay(creature, type, text, pos); - } - } - void sendCreatureReload(std::shared_ptr<Creature> creature) { - if (client) { - client->reloadCreature(creature); - } - } - void sendPrivateMessage(std::shared_ptr<Player> speaker, SpeakClasses type, const std::string &text) { - if (client) { - client->sendPrivateMessage(speaker, type, text); - } - } - void sendCreatureSquare(std::shared_ptr<Creature> creature, SquareColor_t color) { - if (client) { - client->sendCreatureSquare(creature, color); - } - } - void sendCreatureChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) { - if (client) { - client->sendCreatureOutfit(creature, outfit); - } - } - void sendCreatureChangeVisible(std::shared_ptr<Creature> creature, bool visible) { - if (!client || !creature) { - return; - } - - if (creature->getPlayer()) { - if (visible) { - client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); - } else { - static Outfit_t outfit; - client->sendCreatureOutfit(creature, outfit); - } - } else if (canSeeInvisibility()) { - client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); - } else { - auto tile = creature->getTile(); - if (!tile) { - return; - } - int32_t stackpos = tile->getStackposOfCreature(static_self_cast<Player>(), creature); - if (stackpos == -1) { - return; - } - - if (visible) { - client->sendAddCreature(creature, creature->getPosition(), stackpos, false); - } else { - client->sendRemoveTileThing(creature->getPosition(), stackpos); - } - } - } - void sendCreatureLight(std::shared_ptr<Creature> creature) { - if (client) { - client->sendCreatureLight(creature); - } - } - void sendCreatureIcon(std::shared_ptr<Creature> creature) { - if (client && !client->oldProtocol) { - client->sendCreatureIcon(creature); - } - } - void sendUpdateCreature(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendUpdateCreature(creature); - } - } - void sendCreatureWalkthrough(std::shared_ptr<Creature> creature, bool walkthrough) { - if (client) { - client->sendCreatureWalkthrough(creature, walkthrough); - } - } - void sendCreatureShield(std::shared_ptr<Creature> creature) { - if (client) { - client->sendCreatureShield(creature); - } - } - void sendCreatureType(std::shared_ptr<Creature> creature, uint8_t creatureType) { - if (client) { - client->sendCreatureType(creature, creatureType); - } - } - void sendSpellCooldown(uint16_t spellId, uint32_t time) { - if (client) { - client->sendSpellCooldown(spellId, time); - } - } - void sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time) { - if (client) { - client->sendSpellGroupCooldown(groupId, time); - } - } - void sendUseItemCooldown(uint32_t time) const { - if (client) { - client->sendUseItemCooldown(time); - } - } - void reloadCreature(std::shared_ptr<Creature> creature) { - if (client) { - client->reloadCreature(creature); - } - } + // tile + // send methods + void sendAddTileItem(const std::shared_ptr<Tile> &itemTile, const Position &pos, const std::shared_ptr<Item> &item); + void sendUpdateTileItem(const std::shared_ptr<Tile> &updateTile, const Position &pos, const std::shared_ptr<Item> &item); + void sendRemoveTileThing(const Position &pos, int32_t stackpos) const; + void sendUpdateTileCreature(const std::shared_ptr<Creature> &creature); + void sendUpdateTile(const std::shared_ptr<Tile> &updateTile, const Position &pos) const; + + void sendChannelMessage(const std::string &author, const std::string &text, SpeakClasses type, uint16_t channel) const; + void sendChannelEvent(uint16_t channelId, const std::string &playerName, ChannelEvent_t channelEvent) const; + void sendCreatureAppear(const std::shared_ptr<Creature> &creature, const Position &pos, bool isLogin); + void sendCreatureMove(const std::shared_ptr<Creature> &creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport) const; + void sendCreatureTurn(const std::shared_ptr<Creature> &creature); + void sendCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, const Position* pos = nullptr) const; + void sendCreatureReload(const std::shared_ptr<Creature> &creature) const; + void sendPrivateMessage(const std::shared_ptr<Player> &speaker, SpeakClasses type, const std::string &text) const; + void sendCreatureSquare(const std::shared_ptr<Creature> &creature, SquareColor_t color) const; + void sendCreatureChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) const; + void sendCreatureChangeVisible(const std::shared_ptr<Creature> &creature, bool visible); + void sendCreatureLight(const std::shared_ptr<Creature> &creature) const; + void sendCreatureIcon(const std::shared_ptr<Creature> &creature) const; + void sendUpdateCreature(const std::shared_ptr<Creature> &creature) const; + void sendCreatureWalkthrough(const std::shared_ptr<Creature> &creature, bool walkthrough) const; + void sendCreatureShield(const std::shared_ptr<Creature> &creature) const; + void sendCreatureType(const std::shared_ptr<Creature> &creature, uint8_t creatureType) const; + void sendSpellCooldown(uint16_t spellId, uint32_t time) const; + void sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time) const; + void sendUseItemCooldown(uint32_t time) const; + void reloadCreature(const std::shared_ptr<Creature> &creature) const; void sendModalWindow(const ModalWindow &modalWindow); // container void closeAllExternalContainers(); - void sendAddContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> item); - void sendUpdateContainerItem(std::shared_ptr<Container> container, uint16_t slot, std::shared_ptr<Item> newItem); - void sendRemoveContainerItem(std::shared_ptr<Container> container, uint16_t slot); - void sendContainer(uint8_t cid, std::shared_ptr<Container> container, bool hasParent, uint16_t firstIndex) { - if (client) { - client->sendContainer(cid, container, hasParent, firstIndex); - } - } + // container + void sendAddContainerItem(const std::shared_ptr<Container> &container, std::shared_ptr<Item> item); + void sendUpdateContainerItem(const std::shared_ptr<Container> &container, uint16_t slot, const std::shared_ptr<Item> &newItem); + void sendRemoveContainerItem(const std::shared_ptr<Container> &container, uint16_t slot); + void sendContainer(uint8_t cid, const std::shared_ptr<Container> &container, bool hasParent, uint16_t firstIndex) const; // inventory - void sendDepotItems(const ItemsTierCountList &itemMap, uint16_t count) const { - if (client) { - client->sendDepotItems(itemMap, count); - } - } - void sendCloseDepotSearch() const { - if (client) { - client->sendCloseDepotSearch(); - } - } - void sendDepotSearchResultDetail(uint16_t itemId, uint8_t tier, uint32_t depotCount, const ItemVector &depotItems, uint32_t inboxCount, const ItemVector &inboxItems, uint32_t stashCount) const { - if (client) { - client->sendDepotSearchResultDetail(itemId, tier, depotCount, depotItems, inboxCount, inboxItems, stashCount); - } - } - void sendCoinBalance() { - if (client) { - client->sendCoinBalance(); - } - } - void sendInventoryItem(Slots_t slot, std::shared_ptr<Item> item) { - if (client) { - client->sendInventoryItem(slot, item); - } - } - void sendInventoryIds() { - if (client) { - client->sendInventoryIds(); - } - } + void sendDepotItems(const ItemsTierCountList &itemMap, uint16_t count) const; + void sendCloseDepotSearch() const; + void sendDepotSearchResultDetail(uint16_t itemId, uint8_t tier, uint32_t depotCount, const ItemVector &depotItems, uint32_t inboxCount, const ItemVector &inboxItems, uint32_t stashCount) const; + void sendCoinBalance() const; + void sendInventoryItem(Slots_t slot, const std::shared_ptr<Item> &item) const; + void sendInventoryIds() const; void openPlayerContainers(); // Quickloot - void sendLootContainers() { - if (client) { - client->sendLootContainers(); - } - } + void sendLootContainers() const; - void sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) { - if (client) { - client->sendSingleSoundEffect(pos, id, source); - } - } + void sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source) const; - void sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundId, SourceEffect_t mainSource, SoundEffect_t secondarySoundId, SourceEffect_t secondarySource) { - if (client) { - client->sendDoubleSoundEffect(pos, mainSoundId, mainSource, secondarySoundId, secondarySource); - } - } + void sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundId, SourceEffect_t mainSource, SoundEffect_t secondarySoundId, SourceEffect_t secondarySource) const; SoundEffect_t getAttackSoundEffect() const; SoundEffect_t getHitSoundEffect() const; // event methods - void onUpdateTileItem(std::shared_ptr<Tile> tile, const Position &pos, std::shared_ptr<Item> oldItem, const ItemType &oldType, std::shared_ptr<Item> newItem, const ItemType &newType) override; - void onRemoveTileItem(std::shared_ptr<Tile> tile, const Position &pos, const ItemType &iType, std::shared_ptr<Item> item) override; + void onUpdateTileItem(const std::shared_ptr<Tile> &tile, const Position &pos, const std::shared_ptr<Item> &oldItem, const ItemType &oldType, const std::shared_ptr<Item> &newItem, const ItemType &newType) override; + void onRemoveTileItem(const std::shared_ptr<Tile> &tile, const Position &pos, const ItemType &iType, const std::shared_ptr<Item> &item) override; - void onCreatureAppear(std::shared_ptr<Creature> creature, bool isLogin) override; - void onRemoveCreature(std::shared_ptr<Creature> creature, bool isLogout) override; + void onCreatureAppear(const std::shared_ptr<Creature> &creature, bool isLogin) override; + void onRemoveCreature(const std::shared_ptr<Creature> &creature, bool isLogout) override; void onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) override; void onEquipInventory(); @@ -1333,542 +809,182 @@ class Player final : public Creature, public Cylinder, public Bankable { void onFollowCreatureDisappear(bool isLogout) override; // container - void onAddContainerItem(std::shared_ptr<Item> item); - void onUpdateContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem); - void onRemoveContainerItem(std::shared_ptr<Container> container, std::shared_ptr<Item> item); + // container + void onAddContainerItem(const std::shared_ptr<Item> &item); + void onUpdateContainerItem(const std::shared_ptr<Container> &container, const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem); + void onRemoveContainerItem(const std::shared_ptr<Container> &container, const std::shared_ptr<Item> &item); - void onCloseContainer(std::shared_ptr<Container> container); - void onSendContainer(std::shared_ptr<Container> container); - void autoCloseContainers(std::shared_ptr<Container> container); + void onCloseContainer(const std::shared_ptr<Container> &container); + void onSendContainer(const std::shared_ptr<Container> &container); + // close container and its child containers + void autoCloseContainers(const std::shared_ptr<Container> &container); // inventory - void onUpdateInventoryItem(std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem); - void onRemoveInventoryItem(std::shared_ptr<Item> item); + // inventory + void onUpdateInventoryItem(const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem); + void onRemoveInventoryItem(const std::shared_ptr<Item> &item); - void sendCancelMessage(const std::string &msg) const { - if (client) { - client->sendTextMessage(TextMessage(MESSAGE_FAILURE, msg)); - } - } + void sendCancelMessage(const std::string &msg) const; void sendCancelMessage(ReturnValue message) const; - void sendCancelTarget() const { - if (client) { - client->sendCancelTarget(); - } - } - void sendCancelWalk() const { - if (client) { - client->sendCancelWalk(); - } - } - void sendChangeSpeed(std::shared_ptr<Creature> creature, uint16_t newSpeed) const { - if (client) { - client->sendChangeSpeed(creature, newSpeed); - } - } - void sendCreatureHealth(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendCreatureHealth(creature); - } - } - void sendPartyCreatureUpdate(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendPartyCreatureUpdate(creature); - } - } - void sendPartyCreatureShield(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendPartyCreatureShield(creature); - } - } - void sendPartyCreatureSkull(std::shared_ptr<Creature> creature) const { - if (client) { - client->sendPartyCreatureSkull(creature); - } - } - void sendPartyCreatureHealth(std::shared_ptr<Creature> creature, uint8_t healthPercent) const { - if (client) { - client->sendPartyCreatureHealth(creature, healthPercent); - } - } - void sendPartyPlayerMana(std::shared_ptr<Player> player, uint8_t manaPercent) const { - if (client) { - client->sendPartyPlayerMana(player, manaPercent); - } - } - void sendPartyCreatureShowStatus(std::shared_ptr<Creature> creature, bool showStatus) const { - if (client) { - client->sendPartyCreatureShowStatus(creature, showStatus); - } - } - void sendPartyPlayerVocation(std::shared_ptr<Player> player) const { - if (client) { - client->sendPartyPlayerVocation(player); - } - } - void sendPlayerVocation(std::shared_ptr<Player> player) const { - if (client) { - client->sendPlayerVocation(player); - } - } - void sendDistanceShoot(const Position &from, const Position &to, uint16_t type) const { - if (client) { - client->sendDistanceShoot(from, to, type); - } - } - void sendHouseWindow(std::shared_ptr<House> house, uint32_t listId) const; - void sendCreatePrivateChannel(uint16_t channelId, const std::string &channelName) { - if (client) { - client->sendCreatePrivateChannel(channelId, channelName); - } - } + void sendCancelTarget() const; + void sendCancelWalk() const; + void sendChangeSpeed(const std::shared_ptr<Creature> &creature, uint16_t newSpeed) const; + void sendCreatureHealth(const std::shared_ptr<Creature> &creature) const; + void sendPartyCreatureUpdate(const std::shared_ptr<Creature> &creature) const; + void sendPartyCreatureShield(const std::shared_ptr<Creature> &creature) const; + void sendPartyCreatureSkull(const std::shared_ptr<Creature> &creature) const; + void sendPartyCreatureHealth(const std::shared_ptr<Creature> &creature, uint8_t healthPercent) const; + void sendPartyPlayerMana(const std::shared_ptr<Player> &player, uint8_t manaPercent) const; + void sendPartyCreatureShowStatus(const std::shared_ptr<Creature> &creature, bool showStatus) const; + void sendPartyPlayerVocation(const std::shared_ptr<Player> &player) const; + void sendPlayerVocation(const std::shared_ptr<Player> &player) const; + void sendDistanceShoot(const Position &from, const Position &to, uint16_t type) const; + void sendHouseWindow(const std::shared_ptr<House> &house, uint32_t listId) const; + void sendCreatePrivateChannel(uint16_t channelId, const std::string &channelName) const; void sendClosePrivate(uint16_t channelId); void sendIcons(); - void sendIconBakragore(const IconBakragore icon); + void sendIconBakragore(IconBakragore icon) const; void removeBakragoreIcons(); void removeBakragoreIcon(const IconBakragore icon); - void sendClientCheck() const { - if (client) { - client->sendClientCheck(); - } - } - void sendGameNews() const { - if (client) { - client->sendGameNews(); - } - } - void sendMagicEffect(const Position &pos, uint16_t type) const { - if (client) { - client->sendMagicEffect(pos, type); - } - } - void removeMagicEffect(const Position &pos, uint16_t type) const { - if (client) { - client->removeMagicEffect(pos, type); - } - } + void sendClientCheck() const; + void sendGameNews() const; + void sendMagicEffect(const Position &pos, uint16_t type) const; + void removeMagicEffect(const Position &pos, uint16_t type) const; void sendPing(); - void sendPingBack() const { - if (client) { - client->sendPingBack(); - } - } + void sendPingBack() const; void sendStats(); - void sendBasicData() const { - if (client) { - client->sendBasicData(); - } - } - void sendBlessStatus() const { - if (client) { - client->sendBlessStatus(); - } - } - void sendSkills() const { - if (client) { - client->sendSkills(); - } - } - void sendTextMessage(MessageClasses mclass, const std::string &message) const { - if (client) { - client->sendTextMessage(TextMessage(mclass, message)); - } - } - void sendTextMessage(const TextMessage &message) const { - if (client) { - client->sendTextMessage(message); - } - } - void sendReLoginWindow(uint8_t unfairFightReduction) const { - if (client) { - client->sendReLoginWindow(unfairFightReduction); - } - } - void sendTextWindow(std::shared_ptr<Item> item, uint16_t maxlen, bool canWrite) const { - if (client) { - client->sendTextWindow(windowTextId, item, maxlen, canWrite); - } - } - void sendToChannel(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, uint16_t channelId) const { - if (client) { - client->sendToChannel(creature, type, text, channelId); - } - } - void sendShop(std::shared_ptr<Npc> npc) const { - if (client) { - client->sendShop(npc); - } - } + void sendBasicData() const; + void sendBlessStatus() const; + void sendSkills() const; + void sendTextMessage(MessageClasses mclass, const std::string &message) const; + void sendTextMessage(const TextMessage &message) const; + void sendReLoginWindow(uint8_t unfairFightReduction) const; + void sendTextWindow(const std::shared_ptr<Item> &item, uint16_t maxlen, bool canWrite) const; + void sendToChannel(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, uint16_t channelId) const; + void sendShop(const std::shared_ptr<Npc> &npc) const; void sendSaleItemList(const std::map<uint16_t, uint16_t> &inventoryMap) const; - void sendCloseShop() const { - if (client) { - client->sendCloseShop(); - } - } - void sendMarketEnter(uint32_t depotId); - void sendMarketLeave() { - inMarket = false; - if (client) { - client->sendMarketLeave(); - } - } - void sendMarketBrowseItem(uint16_t itemId, const MarketOfferList &buyOffers, const MarketOfferList &sellOffers, uint8_t tier) const { - if (client) { - client->sendMarketBrowseItem(itemId, buyOffers, sellOffers, tier); - } - } - void sendMarketBrowseOwnOffers(const MarketOfferList &buyOffers, const MarketOfferList &sellOffers) const { - if (client) { - client->sendMarketBrowseOwnOffers(buyOffers, sellOffers); - } - } - void sendMarketBrowseOwnHistory(const HistoryMarketOfferList &buyOffers, const HistoryMarketOfferList &sellOffers) const { - if (client) { - client->sendMarketBrowseOwnHistory(buyOffers, sellOffers); - } - } - void sendMarketDetail(uint16_t itemId, uint8_t tier) const { - if (client) { - client->sendMarketDetail(itemId, tier); - } - } - void sendMarketAcceptOffer(const MarketOfferEx &offer) const { - if (client) { - client->sendMarketAcceptOffer(offer); - } - } - void sendMarketCancelOffer(const MarketOfferEx &offer) const { - if (client) { - client->sendMarketCancelOffer(offer); - } - } - void sendTradeItemRequest(const std::string &traderName, std::shared_ptr<Item> item, bool ack) const { - if (client) { - client->sendTradeItemRequest(traderName, item, ack); - } - } - void sendTradeClose() const { - if (client) { - client->sendCloseTrade(); - } - } - void sendWorldLight(LightInfo lightInfo) { - if (client) { - client->sendWorldLight(lightInfo); - } - } - void sendTibiaTime(int32_t time) { - if (client) { - client->sendTibiaTime(time); - } - } - void sendChannelsDialog() { - if (client) { - client->sendChannelsDialog(); - } - } - void sendOpenPrivateChannel(const std::string &receiver) { - if (client) { - client->sendOpenPrivateChannel(receiver); - } - } - void sendExperienceTracker(int64_t rawExp, int64_t finalExp) const { - if (client) { - client->sendExperienceTracker(rawExp, finalExp); - } - } - void sendOutfitWindow() { - if (client) { - client->sendOutfitWindow(); - } - } + void sendCloseShop() const; + void sendMarketEnter(uint32_t depotId) const; + void sendMarketLeave(); + void sendMarketBrowseItem(uint16_t itemId, const MarketOfferList &buyOffers, const MarketOfferList &sellOffers, uint8_t tier) const; + void sendMarketBrowseOwnOffers(const MarketOfferList &buyOffers, const MarketOfferList &sellOffers) const; + void sendMarketBrowseOwnHistory(const HistoryMarketOfferList &buyOffers, const HistoryMarketOfferList &sellOffers) const; + void sendMarketDetail(uint16_t itemId, uint8_t tier) const; + void sendMarketAcceptOffer(const MarketOfferEx &offer) const; + void sendMarketCancelOffer(const MarketOfferEx &offer) const; + void sendTradeItemRequest(const std::string &traderName, const std::shared_ptr<Item> &item, bool ack) const; + void sendTradeClose() const; + void sendWorldLight(LightInfo lightInfo) const; + void sendTibiaTime(int32_t time) const; + void sendChannelsDialog() const; + void sendOpenPrivateChannel(const std::string &receiver) const; + void sendExperienceTracker(int64_t rawExp, int64_t finalExp) const; + void sendOutfitWindow() const; // Imbuements - void onApplyImbuement(Imbuement* imbuement, std::shared_ptr<Item> item, uint8_t slot, bool protectionCharm); - void onClearImbuement(std::shared_ptr<Item> item, uint8_t slot); - void openImbuementWindow(std::shared_ptr<Item> item); - void sendImbuementResult(const std::string message) { - if (client) { - client->sendImbuementResult(message); - } - } - void closeImbuementWindow() const { - if (client) { - client->closeImbuementWindow(); - } - } - void sendPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackpos) { - if (client) { - client->sendPodiumWindow(podium, position, itemId, stackpos); - } - } - void sendCloseContainer(uint8_t cid) { - if (client) { - client->sendCloseContainer(cid); - } - } - - void sendChannel(uint16_t channelId, const std::string &channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) { - if (client) { - client->sendChannel(channelId, channelName, channelUsers, invitedUsers); - } - } - void sendTutorial(uint8_t tutorialId) { - if (client) { - client->sendTutorial(tutorialId); - } - } - void sendAddMarker(const Position &pos, uint8_t markType, const std::string &desc) { - if (client) { - client->sendAddMarker(pos, markType, desc); - } - } - void sendItemInspection(uint16_t itemId, uint8_t itemCount, std::shared_ptr<Item> item, bool cyclopedia) { - if (client) { - client->sendItemInspection(itemId, itemCount, item, cyclopedia); - } - } - void sendCyclopediaCharacterNoData(CyclopediaCharacterInfoType_t characterInfoType, uint8_t errorCode) { - if (client) { - client->sendCyclopediaCharacterNoData(characterInfoType, errorCode); - } - } - void sendCyclopediaCharacterBaseInformation() { - if (client) { - client->sendCyclopediaCharacterBaseInformation(); - } - } - void sendCyclopediaCharacterGeneralStats() { - if (client) { - client->sendCyclopediaCharacterGeneralStats(); - } - } - void sendCyclopediaCharacterCombatStats() { - if (client) { - client->sendCyclopediaCharacterCombatStats(); - } - } - void sendCyclopediaCharacterRecentDeaths(uint16_t page, uint16_t pages, const std::vector<RecentDeathEntry> &entries) { - if (client) { - client->sendCyclopediaCharacterRecentDeaths(page, pages, entries); - } - } - void sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t pages, const std::vector<RecentPvPKillEntry> &entries) { - if (client) { - client->sendCyclopediaCharacterRecentPvPKills(page, pages, entries); - } - } - void sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, std::vector<std::pair<Achievement, uint32_t>> achievementsUnlocked); - void sendCyclopediaCharacterItemSummary(const ItemsTierCountList &inventoryItems, const ItemsTierCountList &storeInboxItems, const StashItemList &supplyStashItems, const ItemsTierCountList &depotBoxItems, const ItemsTierCountList &inboxItems) { - if (client) { - client->sendCyclopediaCharacterItemSummary(inventoryItems, storeInboxItems, supplyStashItems, depotBoxItems, inboxItems); - } - } - void sendCyclopediaCharacterOutfitsMounts() { - if (client) { - client->sendCyclopediaCharacterOutfitsMounts(); - } - } - void sendCyclopediaCharacterStoreSummary() { - if (client) { - client->sendCyclopediaCharacterStoreSummary(); - } - } - void sendCyclopediaCharacterInspection() { - if (client) { - client->sendCyclopediaCharacterInspection(); - } - } - void sendCyclopediaCharacterBadges() { - if (client) { - client->sendCyclopediaCharacterBadges(); - } - } - void sendCyclopediaCharacterTitles() { - if (client) { - client->sendCyclopediaCharacterTitles(); - } - } - void sendHighscoresNoData() { - if (client) { - client->sendHighscoresNoData(); - } - } - void sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) { - if (client) { - client->sendHighscores(characters, categoryId, vocationId, page, pages, updateTimer); - } - } - void addAsyncOngoingTask(uint64_t flags) { - asyncOngoingTasks |= flags; - } - bool hasAsyncOngoingTask(uint64_t flags) const { - return (asyncOngoingTasks & flags); - } - void resetAsyncOngoingTask(uint64_t flags) { - asyncOngoingTasks &= ~(flags); - } - void sendEnterWorld() { - if (client) { - client->sendEnterWorld(); - } - } - void sendFightModes() { - if (client) { - client->sendFightModes(); - } - } - void sendNetworkMessage(const NetworkMessage &message) { - if (client) { - client->writeToOutputBuffer(message); - } - } - - void receivePing() { - lastPong = OTSYS_TIME(); - } - - void sendOpenStash(bool isNpc = false) { - if (client && ((getLastDepotId() != -1) || isNpc)) { - client->sendOpenStash(); - } - } - - void sendTakeScreenshot(Screenshot_t screenshotType) { - if (client) { - client->sendTakeScreenshot(screenshotType); - } - } + void onApplyImbuement(const Imbuement* imbuement, const std::shared_ptr<Item> &item, uint8_t slot, bool protectionCharm); + void onClearImbuement(const std::shared_ptr<Item> &item, uint8_t slot); + void openImbuementWindow(const std::shared_ptr<Item> &item); + void sendImbuementResult(const std::string &message) const; + void closeImbuementWindow() const; + void sendPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos) const; + void sendCloseContainer(uint8_t cid) const; + + void sendChannel(uint16_t channelId, const std::string &channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) const; + void sendTutorial(uint8_t tutorialId) const; + void sendAddMarker(const Position &pos, uint8_t markType, const std::string &desc) const; + void sendItemInspection(uint16_t itemId, uint8_t itemCount, const std::shared_ptr<Item> &item, bool cyclopedia) const; + void sendCyclopediaCharacterNoData(CyclopediaCharacterInfoType_t characterInfoType, uint8_t errorCode) const; + void sendCyclopediaCharacterBaseInformation() const; + void sendCyclopediaCharacterGeneralStats() const; + void sendCyclopediaCharacterCombatStats() const; + void sendCyclopediaCharacterRecentDeaths(uint16_t page, uint16_t pages, const std::vector<RecentDeathEntry> &entries) const; + void sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t pages, const std::vector<RecentPvPKillEntry> &entries) const; + void sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, const std::vector<std::pair<Achievement, uint32_t>> &achievementsUnlocked) const; + void sendCyclopediaCharacterItemSummary(const ItemsTierCountList &inventoryItems, const ItemsTierCountList &storeInboxItems, const StashItemList &supplyStashItems, const ItemsTierCountList &depotBoxItems, const ItemsTierCountList &inboxItems) const; + void sendCyclopediaCharacterOutfitsMounts() const; + void sendCyclopediaCharacterStoreSummary() const; + void sendCyclopediaCharacterInspection() const; + void sendCyclopediaCharacterBadges() const; + void sendCyclopediaCharacterTitles() const; + void sendHighscoresNoData() const; + void sendHighscores(const std::vector<HighscoreCharacter> &characters, uint8_t categoryId, uint32_t vocationId, uint16_t page, uint16_t pages, uint32_t updateTimer) const; + void addAsyncOngoingTask(uint64_t flags); + bool hasAsyncOngoingTask(uint64_t flags) const; + void resetAsyncOngoingTask(uint64_t flags); + void sendEnterWorld() const; + void sendFightModes() const; + void sendNetworkMessage(const NetworkMessage &message) const; + + void receivePing(); + + void sendOpenStash(bool isNpc = false) const; + + void sendTakeScreenshot(Screenshot_t screenshotType) const; void onThink(uint32_t interval) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void setNextAction(int64_t time) { - if (time > nextAction) { - nextAction = time; - } - } - bool canDoAction() const { - return nextAction <= OTSYS_TIME(); - } + void setNextAction(int64_t time); + bool canDoAction() const; - void setNextPotionAction(int64_t time) { - if (time > nextPotionAction) { - nextPotionAction = time; - } - } - bool canDoPotionAction() const { - return nextPotionAction <= OTSYS_TIME(); - } + void setNextPotionAction(int64_t time); + bool canDoPotionAction() const; void cancelPush(); - void setModuleDelay(uint8_t byteortype, int16_t delay) { - moduleDelayMap[byteortype] = OTSYS_TIME() + delay; - } + void setModuleDelay(uint8_t byteortype, int16_t delay); - bool canRunModule(uint8_t byteortype) { - if (!moduleDelayMap[byteortype]) { - return true; - } - return moduleDelayMap[byteortype] <= OTSYS_TIME(); - } + bool canRunModule(uint8_t byteortype); uint32_t getNextActionTime() const; uint32_t getNextPotionActionTime() const; std::shared_ptr<Item> getWriteItem(uint32_t &windowTextId, uint16_t &maxWriteLen); - void setWriteItem(std::shared_ptr<Item> item, uint16_t maxWriteLen = 0); + void setWriteItem(const std::shared_ptr<Item> &item, uint16_t maxWriteLen = 0); std::shared_ptr<House> getEditHouse(uint32_t &windowTextId, uint32_t &listId); - void setEditHouse(std::shared_ptr<House> house, uint32_t listId = 0); + void setEditHouse(const std::shared_ptr<House> &house, uint32_t listId = 0); void learnInstantSpell(const std::string &spellName); void forgetInstantSpell(const std::string &spellName); bool hasLearnedInstantSpell(const std::string &spellName) const; - void updateRegeneration(); + void updateRegeneration() const; - void setScheduledSaleUpdate(bool scheduled) { - scheduledSaleUpdate = scheduled; - } + void setScheduledSaleUpdate(bool scheduled); - bool getScheduledSaleUpdate() { - return scheduledSaleUpdate; - } + bool getScheduledSaleUpdate() const; - bool inPushEvent() { - return inEventMovePush; - } + bool inPushEvent() const; - void pushEvent(bool b) { - inEventMovePush = b; - } + void pushEvent(bool b); - bool walkExhausted() { - if (hasCondition(CONDITION_PARALYZE)) { - return lastWalking > OTSYS_TIME(); - } + bool walkExhausted() const; - return false; - } + void setWalkExhaust(int64_t value); - void setWalkExhaust(int64_t value) { - lastWalking = OTSYS_TIME() + value; - } - - const std::map<uint8_t, OpenContainer> &getOpenContainers() const { - return openContainers; - } + const std::map<uint8_t, OpenContainer> &getOpenContainers() const; - uint16_t getBaseXpGain() const { - return baseXpGain; - } - void setBaseXpGain(uint16_t value) { - baseXpGain = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); - } - uint16_t getVoucherXpBoost() const { - return voucherXpBoost; - } - void setVoucherXpBoost(uint16_t value) { - voucherXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); - } - uint16_t getGrindingXpBoost() const { - return grindingXpBoost; - } - void setGrindingXpBoost(uint16_t value) { - grindingXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); - } - uint16_t getXpBoostPercent() const { - return xpBoostPercent; - } - void setXpBoostPercent(uint16_t percent) { - xpBoostPercent = percent; - } - uint16_t getStaminaXpBoost() const { - return staminaXpBoost; - } - void setStaminaXpBoost(uint16_t value) { - staminaXpBoost = std::min<uint16_t>(std::numeric_limits<uint16_t>::max(), value); - } + uint16_t getBaseXpGain() const; + void setBaseXpGain(uint16_t value); + uint16_t getVoucherXpBoost() const; + void setVoucherXpBoost(uint16_t value); + uint16_t getGrindingXpBoost() const; + uint16_t getDisplayGrindingXpBoost() const; + void setGrindingXpBoost(uint16_t value); + uint16_t getXpBoostPercent() const; + uint16_t getDisplayXpBoostPercent() const; + void setXpBoostPercent(uint16_t percent); + uint16_t getStaminaXpBoost() const; + void setStaminaXpBoost(uint16_t value); - void setXpBoostTime(uint16_t timeLeft) { - // only allow time boosts of 12 hours or less - if (timeLeft > 12 * 3600) { - xpBoostTime = 12 * 3600; - return; - } - xpBoostTime = timeLeft; - } + void setXpBoostTime(uint16_t timeLeft); - uint16_t getXpBoostTime() { - return xpBoostTime; - } + uint16_t getXpBoostTime() const; - int32_t getIdleTime() const { - return idleTime; - } + int32_t getIdleTime() const; void setTraining(bool value); @@ -1876,258 +992,48 @@ class Player final : public Creature, public Cylinder, public Bankable { void removeItemImbuementStats(const Imbuement* imbuement); void updateImbuementTrackerStats() const; + // User Interface action exhaustion bool isUIExhausted(uint32_t exhaustionTime = 250) const; void updateUIExhausted(); - bool isQuickLootListedItem(std::shared_ptr<Item> item) const { - if (!item) { - return false; - } - - auto it = std::find(quickLootListItemIds.begin(), quickLootListItemIds.end(), item->getID()); - return it != quickLootListItemIds.end(); - } + bool isQuickLootListedItem(const std::shared_ptr<Item> &item) const; - bool updateKillTracker(std::shared_ptr<Container> corpse, const std::string &playerName, const Outfit_t creatureOutfit) const { - if (client) { - client->sendKillTrackerUpdate(corpse, playerName, creatureOutfit); - return true; - } + bool updateKillTracker(const std::shared_ptr<Container> &corpse, const std::string &playerName, const Outfit_t &creatureOutfit) const; - return false; - } + void updatePartyTrackerAnalyzer() const; - void updatePartyTrackerAnalyzer() const { - if (client && m_party) { - client->updatePartyTrackerAnalyzer(m_party); - } - } - - void sendLootStats(std::shared_ptr<Item> item, uint8_t count); - void updateSupplyTracker(std::shared_ptr<Item> item); + void sendLootStats(const std::shared_ptr<Item> &item, uint8_t count); + void updateSupplyTracker(const std::shared_ptr<Item> &item); void updateImpactTracker(CombatType_t type, int32_t amount) const; - void updateInputAnalyzer(CombatType_t type, int32_t amount, std::string target) { - if (client) { - client->sendUpdateInputAnalyzer(type, amount, target); - } - } - - void createLeaderTeamFinder(NetworkMessage &msg) { - if (client) { - client->createLeaderTeamFinder(msg); - } - } - void sendLeaderTeamFinder(bool reset) { - if (client) { - client->sendLeaderTeamFinder(reset); - } - } - void sendTeamFinderList() { - if (client) { - client->sendTeamFinderList(); - } - } - void sendCreatureHelpers(uint32_t creatureId, uint16_t helpers) { - if (client) { - client->sendCreatureHelpers(creatureId, helpers); - } - } - - void setItemCustomPrice(uint16_t itemId, uint64_t price) { - itemPriceMap[itemId] = price; - } - uint32_t getCharmPoints() { - return charmPoints; - } - void setCharmPoints(uint32_t points) { - charmPoints = points; - } - bool hasCharmExpansion() { - return charmExpansion; - } - void setCharmExpansion(bool onOff) { - charmExpansion = onOff; - } - void setUsedRunesBit(int32_t bit) { - UsedRunesBit = bit; - } - int32_t getUsedRunesBit() { - return UsedRunesBit; - } - void setUnlockedRunesBit(int32_t bit) { - UnlockedRunesBit = bit; - } - int32_t getUnlockedRunesBit() { - return UnlockedRunesBit; - } - void setImmuneCleanse(ConditionType_t conditiontype) { - cleanseCondition.first = conditiontype; - cleanseCondition.second = OTSYS_TIME() + 10000; - } - bool isImmuneCleanse(ConditionType_t conditiontype) { - uint64_t timenow = OTSYS_TIME(); - if ((cleanseCondition.first == conditiontype) - && (timenow <= cleanseCondition.second)) { - return true; - } - return false; - } + void updateInputAnalyzer(CombatType_t type, int32_t amount, const std::string &target) const; + + void createLeaderTeamFinder(NetworkMessage &msg) const; + void sendLeaderTeamFinder(bool reset) const; + void sendTeamFinderList() const; + void sendCreatureHelpers(uint32_t creatureId, uint16_t helpers) const; + + void setItemCustomPrice(uint16_t itemId, uint64_t price); + uint32_t getCharmPoints() const; + void setCharmPoints(uint32_t points); + bool hasCharmExpansion() const; + void setCharmExpansion(bool onOff); + void setUsedRunesBit(int32_t bit); + int32_t getUsedRunesBit() const; + void setUnlockedRunesBit(int32_t bit); + int32_t getUnlockedRunesBit() const; + void setImmuneCleanse(ConditionType_t conditiontype); + bool isImmuneCleanse(ConditionType_t conditiontype) const; void setImmuneFear(); bool isImmuneFear() const; - uint16_t parseRacebyCharm(charmRune_t charmId, bool set, uint16_t newRaceid) { - uint16_t raceid = 0; - switch (charmId) { - case CHARM_WOUND: - if (set) { - charmRuneWound = newRaceid; - } else { - raceid = charmRuneWound; - } - break; - case CHARM_ENFLAME: - if (set) { - charmRuneEnflame = newRaceid; - } else { - raceid = charmRuneEnflame; - } - break; - case CHARM_POISON: - if (set) { - charmRunePoison = newRaceid; - } else { - raceid = charmRunePoison; - } - break; - case CHARM_FREEZE: - if (set) { - charmRuneFreeze = newRaceid; - } else { - raceid = charmRuneFreeze; - } - break; - case CHARM_ZAP: - if (set) { - charmRuneZap = newRaceid; - } else { - raceid = charmRuneZap; - } - break; - case CHARM_CURSE: - if (set) { - charmRuneCurse = newRaceid; - } else { - raceid = charmRuneCurse; - } - break; - case CHARM_CRIPPLE: - if (set) { - charmRuneCripple = newRaceid; - } else { - raceid = charmRuneCripple; - } - break; - case CHARM_PARRY: - if (set) { - charmRuneParry = newRaceid; - } else { - raceid = charmRuneParry; - } - break; - case CHARM_DODGE: - if (set) { - charmRuneDodge = newRaceid; - } else { - raceid = charmRuneDodge; - } - break; - case CHARM_ADRENALINE: - if (set) { - charmRuneAdrenaline = newRaceid; - } else { - raceid = charmRuneAdrenaline; - } - break; - case CHARM_NUMB: - if (set) { - charmRuneNumb = newRaceid; - } else { - raceid = charmRuneNumb; - } - break; - case CHARM_CLEANSE: - if (set) { - charmRuneCleanse = newRaceid; - } else { - raceid = charmRuneCleanse; - } - break; - case CHARM_BLESS: - if (set) { - charmRuneBless = newRaceid; - } else { - raceid = charmRuneBless; - } - break; - case CHARM_SCAVENGE: - if (set) { - charmRuneScavenge = newRaceid; - } else { - raceid = charmRuneScavenge; - } - break; - case CHARM_GUT: - if (set) { - charmRuneGut = newRaceid; - } else { - raceid = charmRuneGut; - } - break; - case CHARM_LOW: - if (set) { - charmRuneLowBlow = newRaceid; - } else { - raceid = charmRuneLowBlow; - } - break; - case CHARM_DIVINE: - if (set) { - charmRuneDivine = newRaceid; - } else { - raceid = charmRuneDivine; - } - break; - case CHARM_VAMP: - if (set) { - charmRuneVamp = newRaceid; - } else { - raceid = charmRuneVamp; - } - break; - case CHARM_VOID: - if (set) { - charmRuneVoid = newRaceid; - } else { - raceid = charmRuneVoid; - } - break; - default: - raceid = 0; - break; - } - return raceid; - } + uint16_t parseRacebyCharm(charmRune_t charmId, bool set, uint16_t newRaceid); uint64_t getItemCustomPrice(uint16_t itemId, bool buyPrice = false) const; uint16_t getFreeBackpackSlots() const; bool canAutoWalk(const Position &toPosition, const std::function<void()> &function, uint32_t delay = 500); - void sendMessageDialog(const std::string &message) const { - if (client) { - client->sendMessageDialog(message); - } - } + void sendMessageDialog(const std::string &message) const; // Account bool setAccount(uint32_t accountId); @@ -2139,233 +1045,69 @@ class Player final : public Creature, public Cylinder, public Bankable { void initializePrey(); void removePreySlotById(PreySlot_t slotid); - void sendPreyData() const { - if (client) { - for (const std::unique_ptr<PreySlot> &slot : preys) { - client->sendPreyData(slot); - } - - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards()); - } - } - - void sendPreyTimeLeft(const std::unique_ptr<PreySlot> &slot) const { - if (g_configManager().getBoolean(PREY_ENABLED) && client) { - client->sendPreyTimeLeft(slot); - } - } - - void reloadPreySlot(PreySlot_t slotid) { - if (g_configManager().getBoolean(PREY_ENABLED) && client) { - client->sendPreyData(getPreySlotById(slotid)); - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - } + void sendPreyData() const; - const std::unique_ptr<PreySlot> &getPreySlotById(PreySlot_t slotid) { - if (auto it = std::find_if(preys.begin(), preys.end(), [slotid](const std::unique_ptr<PreySlot> &preyIt) { - return preyIt->id == slotid; - }); - it != preys.end()) { - return *it; - } + void sendPreyTimeLeft(const std::unique_ptr<PreySlot> &slot) const; - return PreySlotNull; - } + void reloadPreySlot(PreySlot_t slotid); - bool setPreySlotClass(std::unique_ptr<PreySlot> &slot) { - if (getPreySlotById(slot->id)) { - return false; - } + const std::unique_ptr<PreySlot> &getPreySlotById(PreySlot_t slotid); - preys.emplace_back(std::move(slot)); - return true; - } + bool setPreySlotClass(std::unique_ptr<PreySlot> &slot); - bool usePreyCards(uint16_t amount) { - if (preyCards < amount) { - return false; - } + bool usePreyCards(uint16_t amount); - preyCards -= amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - return true; - } + void addPreyCards(uint64_t amount); - void addPreyCards(uint64_t amount) { - preyCards += amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - } - - uint64_t getPreyCards() const { - return preyCards; - } - - uint32_t getPreyRerollPrice() const { - return getLevel() * g_configManager().getNumber(PREY_REROLL_PRICE_LEVEL); - } + uint64_t getPreyCards() const; - std::vector<uint16_t> getPreyBlackList() const { - std::vector<uint16_t> rt; - for (const std::unique_ptr<PreySlot> &slot : preys) { - if (slot) { - if (slot->isOccupied()) { - rt.push_back(slot->selectedRaceId); - } - for (uint16_t raceId : slot->raceIdList) { - rt.push_back(raceId); - } - } - } + uint32_t getPreyRerollPrice() const; - return rt; - } + std::vector<uint16_t> getPreyBlackList() const; - const std::unique_ptr<PreySlot> &getPreyWithMonster(uint16_t raceId) const { - if (!g_configManager().getBoolean(PREY_ENABLED)) { - return PreySlotNull; - } - - if (auto it = std::find_if(preys.begin(), preys.end(), [raceId](const std::unique_ptr<PreySlot> &it) { - return it->selectedRaceId == raceId; - }); - it != preys.end()) { - return *it; - } - - return PreySlotNull; - } + const std::unique_ptr<PreySlot> &getPreyWithMonster(uint16_t raceId) const; // Task hunting system void initializeTaskHunting(); - bool isCreatureUnlockedOnTaskHunting(const std::shared_ptr<MonsterType> mtype) const; - - bool setTaskHuntingSlotClass(std::unique_ptr<TaskHuntingSlot> &slot) { - if (getTaskHuntingSlotById(slot->id)) { - return false; - } - - taskHunting.emplace_back(std::move(slot)); - return true; - } - - void reloadTaskSlot(PreySlot_t slotid) { - if (g_configManager().getBoolean(TASK_HUNTING_ENABLED) && client) { - client->sendTaskHuntingData(getTaskHuntingSlotById(slotid)); - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - } - - const std::unique_ptr<TaskHuntingSlot> &getTaskHuntingSlotById(PreySlot_t slotid) { - if (auto it = std::find_if(taskHunting.begin(), taskHunting.end(), [slotid](const std::unique_ptr<TaskHuntingSlot> &itTask) { - return itTask->id == slotid; - }); - it != taskHunting.end()) { - return *it; - } - - return TaskHuntingSlotNull; - } - - std::vector<uint16_t> getTaskHuntingBlackList() const { - std::vector<uint16_t> rt; - - std::for_each(taskHunting.begin(), taskHunting.end(), [&rt](const std::unique_ptr<TaskHuntingSlot> &slot) { - if (slot->isOccupied()) { - rt.push_back(slot->selectedRaceId); - } else { - std::for_each(slot->raceIdList.begin(), slot->raceIdList.end(), [&rt](uint16_t raceId) { - rt.push_back(raceId); - }); - } - }); + bool isCreatureUnlockedOnTaskHunting(const std::shared_ptr<MonsterType> &mtype) const; - return rt; - } + bool setTaskHuntingSlotClass(std::unique_ptr<TaskHuntingSlot> &slot); - void sendTaskHuntingData() const { - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - for (const std::unique_ptr<TaskHuntingSlot> &slot : taskHunting) { - if (slot) { - client->sendTaskHuntingData(slot); - } - } - } - } + void reloadTaskSlot(PreySlot_t slotid); - void addTaskHuntingPoints(uint64_t amount) { - taskHuntingPoints += amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - } + const std::unique_ptr<TaskHuntingSlot> &getTaskHuntingSlotById(PreySlot_t slotid); - bool useTaskHuntingPoints(uint64_t amount) { - if (taskHuntingPoints < amount) { - return false; - } + std::vector<uint16_t> getTaskHuntingBlackList() const; - taskHuntingPoints -= amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints()); - } - return true; - } + void sendTaskHuntingData() const; - uint64_t getTaskHuntingPoints() const { - return taskHuntingPoints; - } + void addTaskHuntingPoints(uint64_t amount); - uint32_t getTaskHuntingRerollPrice() const { - return getLevel() * g_configManager().getNumber(TASK_HUNTING_REROLL_PRICE_LEVEL); - } + bool useTaskHuntingPoints(uint64_t amount); - const std::unique_ptr<TaskHuntingSlot> &getTaskHuntingWithCreature(uint16_t raceId) const { - if (!g_configManager().getBoolean(TASK_HUNTING_ENABLED)) { - return TaskHuntingSlotNull; - } + uint64_t getTaskHuntingPoints() const; - if (auto it = std::find_if(taskHunting.begin(), taskHunting.end(), [raceId](const std::unique_ptr<TaskHuntingSlot> &itTask) { - return itTask->selectedRaceId == raceId; - }); - it != taskHunting.end()) { - return *it; - } + uint32_t getTaskHuntingRerollPrice() const; - return TaskHuntingSlotNull; - } + const std::unique_ptr<TaskHuntingSlot> &getTaskHuntingWithCreature(uint16_t raceId) const; - uint32_t getLoyaltyPoints() const { - return loyaltyPoints; - } + uint32_t getLoyaltyPoints() const; - void setLoyaltyBonus(uint16_t bonus) { - loyaltyBonusPercent = bonus; - sendSkills(); - } - void setLoyaltyTitle(std::string title) { - loyaltyTitle = title; - } - std::string getLoyaltyTitle() const { - return loyaltyTitle; - } - uint16_t getLoyaltyBonus() const { - return loyaltyBonusPercent; - } + void setLoyaltyBonus(uint16_t bonus); + void setLoyaltyTitle(std::string title); + std::string getLoyaltyTitle() const; + uint16_t getLoyaltyBonus() const; - // Depot search system + /******************************************************************************* + * Depot search system + ******************************************************************************/ void requestDepotItems(); void requestDepotSearchItem(uint16_t itemId, uint8_t tier); void retrieveAllItemsFromDepotSearch(uint16_t itemId, uint8_t tier, bool isDepot); void openContainerFromDepotSearch(const Position &pos); std::shared_ptr<Item> getItemFromDepotSearch(uint16_t itemId, const Position &pos); - std::pair<std::vector<std::shared_ptr<Item>>, std::map<uint16_t, std::map<uint8_t, uint32_t>>> requestLockerItems(std::shared_ptr<DepotLocker> depotLocker, bool sendToClient = false, uint8_t tier = 0) const; + std::pair<std::vector<std::shared_ptr<Item>>, std::map<uint16_t, std::map<uint8_t, uint32_t>>> requestLockerItems(const std::shared_ptr<DepotLocker> &depotLocker, bool sendToClient = false, uint8_t tier = 0) const; /** This function returns a pair of an array of items and a 16-bit integer from a DepotLocker instance, a 8-bit byte and a 16-bit integer. @@ -2379,13 +1121,13 @@ class Player final : public Creature, public Cylinder, public Bankable { const std::shared_ptr<DepotLocker> &depotLocker, uint8_t tier, uint16_t itemId - ); + ) const; bool saySpell( SpeakClasses type, const std::string &text, bool ghostMode, - Spectators* spectatorsPtr = nullptr, + const Spectators* spectatorsPtr = nullptr, const Position* pos = nullptr ); @@ -2395,205 +1137,67 @@ class Player final : public Creature, public Cylinder, public Bankable { void forgeResourceConversion(ForgeAction_t actionType); void forgeHistory(uint8_t page) const; - void sendOpenForge() const { - if (client) { - client->sendOpenForge(); - } - } - void sendForgeError(ReturnValue returnValue) const { - if (client) { - client->sendForgeError(returnValue); - } - } - void sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId, uint8_t leftTier, uint16_t rightItemId, uint8_t rightTier, bool success, uint8_t bonus, uint8_t coreCount, bool convergence) const { - if (client) { - client->sendForgeResult(actionType, leftItemId, leftTier, rightItemId, rightTier, success, bonus, coreCount, convergence); - } - } - void sendForgeHistory(uint8_t page) const { - if (client) { - client->sendForgeHistory(page); - } - } - void closeForgeWindow() const { - if (client) { - client->closeForgeWindow(); - } - } + void sendOpenForge() const; + void sendForgeError(ReturnValue returnValue) const; + void sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId, uint8_t leftTier, uint16_t rightItemId, uint8_t rightTier, bool success, uint8_t bonus, uint8_t coreCount, bool convergence) const; + void sendForgeHistory(uint8_t page) const; + void closeForgeWindow() const; - void setForgeDusts(uint64_t amount) { - forgeDusts = amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); - } - } - void addForgeDusts(uint64_t amount) { - forgeDusts += amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); - } - } - void removeForgeDusts(uint64_t amount) { - forgeDusts = std::max<uint64_t>(0, forgeDusts - amount); - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); - } - } - uint64_t getForgeDusts() const { - return forgeDusts; - } + void setForgeDusts(uint64_t amount); + void addForgeDusts(uint64_t amount); + void removeForgeDusts(uint64_t amount); + uint64_t getForgeDusts() const; - void addForgeDustLevel(uint64_t amount) { - forgeDustLevel += amount; - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); - } - } - void removeForgeDustLevel(uint64_t amount) { - forgeDustLevel = std::max<uint64_t>(0, forgeDustLevel - amount); - if (client) { - client->sendResourcesBalance(getMoney(), getBankBalance(), getPreyCards(), getTaskHuntingPoints(), getForgeDusts()); - } - } - uint64_t getForgeDustLevel() const { - return forgeDustLevel; - } + void addForgeDustLevel(uint64_t amount); + void removeForgeDustLevel(uint64_t amount); + uint64_t getForgeDustLevel() const; - std::vector<ForgeHistory> &getForgeHistory() { - return forgeHistoryVector; - } + std::vector<ForgeHistory> &getForgeHistory(); - void setForgeHistory(const ForgeHistory &history) { - forgeHistoryVector.push_back(history); - } + void setForgeHistory(const ForgeHistory &history); void registerForgeHistoryDescription(ForgeHistory history); - void setBossPoints(uint32_t amount) { - bossPoints = amount; - } - void addBossPoints(uint32_t amount) { - bossPoints += amount; - } - void removeBossPoints(uint32_t amount) { - bossPoints = std::max<uint32_t>(0, bossPoints - amount); - } - uint32_t getBossPoints() const { - return bossPoints; - } - void sendBosstiaryCooldownTimer() const { - if (client) { - client->sendBosstiaryCooldownTimer(); - } - } + void setBossPoints(uint32_t amount); + void addBossPoints(uint32_t amount); + void removeBossPoints(uint32_t amount); + uint32_t getBossPoints() const; + void sendBosstiaryCooldownTimer() const; - void setSlotBossId(uint8_t slotId, uint32_t bossId) { - if (slotId == 1) { - bossIdSlotOne = bossId; - } else { - bossIdSlotTwo = bossId; - } - if (client) { - client->parseSendBosstiarySlots(); - } - } - uint32_t getSlotBossId(uint8_t slotId) const { - if (slotId == 1) { - return bossIdSlotOne; - } else { - return bossIdSlotTwo; - } - } + void setSlotBossId(uint8_t slotId, uint32_t bossId); + uint32_t getSlotBossId(uint8_t slotId) const; - void addRemoveTime() { - bossRemoveTimes = bossRemoveTimes + 1; - } - void setRemoveBossTime(uint8_t newRemoveTimes) { - bossRemoveTimes = newRemoveTimes; - } - uint8_t getRemoveTimes() const { - return bossRemoveTimes; - } + void addRemoveTime(); + void setRemoveBossTime(uint8_t newRemoveTimes); + uint8_t getRemoveTimes() const; - void sendMonsterPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackpos) const { - if (client) { - client->sendMonsterPodiumWindow(podium, position, itemId, stackpos); - } - } + void sendMonsterPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos) const; - void sendBosstiaryEntryChanged(uint32_t bossid) { - if (client) { - client->sendBosstiaryEntryChanged(bossid); - } - } + void sendBosstiaryEntryChanged(uint32_t bossid) const; - void sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> items) const { - if (client) { - client->sendInventoryImbuements(items); - } - } + void sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> &items) const; /******************************************************************************* * Hazard system ******************************************************************************/ // Parser - void parseAttackRecvHazardSystem(CombatDamage &damage, std::shared_ptr<Monster> monster); - void parseAttackDealtHazardSystem(CombatDamage &damage, std::shared_ptr<Monster> monster); + void parseAttackRecvHazardSystem(CombatDamage &damage, const std::shared_ptr<Monster> &monster); + void parseAttackDealtHazardSystem(CombatDamage &damage, const std::shared_ptr<Monster> &monster) const; // Points increase: void setHazardSystemPoints(int32_t amount); // Points get: - uint16_t getHazardSystemPoints() const { - int32_t points = 0; - points = getStorageValue(STORAGEVALUE_HAZARDCOUNT); - if (points <= 0) { - return 0; - } - return static_cast<uint16_t>(std::max<int32_t>(0, std::min<int32_t>(0xFFFF, points))); - } + uint16_t getHazardSystemPoints() const; /*******************************************************************************/ // Concoction system - void updateConcoction(uint16_t itemId, uint16_t timeLeft) { - if (timeLeft == 0) { - activeConcoctions.erase(itemId); - } else { - activeConcoctions[itemId] = timeLeft; - } - } - std::map<uint16_t, uint16_t> getActiveConcoctions() const { - return activeConcoctions; - } - bool isConcoctionActive(Concoction_t concotion) const { - uint16_t itemId = static_cast<uint16_t>(concotion); - if (!activeConcoctions.contains(itemId)) { - return false; - } - auto timeLeft = activeConcoctions.at(itemId); - return timeLeft > 0; - } + void updateConcoction(uint16_t itemId, uint16_t timeLeft); + std::map<uint16_t, uint16_t> getActiveConcoctions() const; + bool isConcoctionActive(Concoction_t concotion) const; - bool checkAutoLoot(bool isBoss) const { - if (!g_configManager().getBoolean(AUTOLOOT)) { - return false; - } - if (g_configManager().getBoolean(VIP_SYSTEM_ENABLED) && g_configManager().getBoolean(VIP_AUTOLOOT_VIP_ONLY) && !isVip()) { - return false; - } - - auto featureKV = kv()->scoped("features")->get("autoloot"); - auto value = featureKV.has_value() ? featureKV->getNumber() : 0; - if (value == 2) { - return true; - } else if (value == 1) { - return !isBoss; - } - return false; - } + bool checkAutoLoot(bool isBoss) const; - QuickLootFilter_t getQuickLootFilter() const { - return quickLootFilter; - } + QuickLootFilter_t getQuickLootFilter() const; // Get specific inventory item from itemid std::vector<std::shared_ptr<Item>> getInventoryItemsFromId(uint16_t itemId, bool ignore = true) const; @@ -2669,13 +1273,13 @@ class Player final : public Creature, public Cylinder, public Bankable { std::vector<std::shared_ptr<Condition>> getMuteConditions() const; - void checkTradeState(std::shared_ptr<Item> item); - bool hasCapacity(std::shared_ptr<Item> item, uint32_t count) const; + void checkTradeState(const std::shared_ptr<Item> &item); + bool hasCapacity(const std::shared_ptr<Item> &item, uint32_t count) const; - void checkLootContainers(std::shared_ptr<Container> item); + void checkLootContainers(const std::shared_ptr<Container> &item); - void gainExperience(uint64_t exp, std::shared_ptr<Creature> target); - void addExperience(std::shared_ptr<Creature> target, uint64_t exp, bool sendText = false); + void gainExperience(uint64_t exp, const std::shared_ptr<Creature> &target); + void addExperience(const std::shared_ptr<Creature> &target, uint64_t exp, bool sendText = false); void removeExperience(uint64_t exp, bool sendText = false); void updateInventoryWeight(); @@ -2685,37 +1289,37 @@ class Player final : public Creature, public Cylinder, public Bankable { */ void updateInventoryImbuement(); - void setNextWalkActionTask(std::shared_ptr<Task> task); - void setNextWalkTask(std::shared_ptr<Task> task); - void setNextActionTask(std::shared_ptr<Task> task, bool resetIdleTime = true); - void setNextActionPushTask(std::shared_ptr<Task> task); - void setNextPotionActionTask(std::shared_ptr<Task> task); + void setNextWalkActionTask(const std::shared_ptr<Task> &task); + void setNextWalkTask(const std::shared_ptr<Task> &task); + void setNextActionTask(const std::shared_ptr<Task> &task, bool resetIdleTime = true); + void setNextActionPushTask(const std::shared_ptr<Task> &task); + void setNextPotionActionTask(const std::shared_ptr<Task> &task); - void death(std::shared_ptr<Creature> lastHitCreature) override; + void death(const std::shared_ptr<Creature> &lastHitCreature) override; bool spawn(); void despawn(); - bool dropCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_ptr<Creature> mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) override; - std::shared_ptr<Item> getCorpse(std::shared_ptr<Creature> lastHitCreature, std::shared_ptr<Creature> mostDamageCreature) override; + bool dropCorpse(const std::shared_ptr<Creature> &lastHitCreature, const std::shared_ptr<Creature> &mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) override; + std::shared_ptr<Item> getCorpse(const std::shared_ptr<Creature> &lastHitCreature, const std::shared_ptr<Creature> &mostDamageCreature) override; // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; - void addThing(std::shared_ptr<Thing>) override { } - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; + void addThing(const std::shared_ptr<Thing> &) override { } + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) override; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) override; - int32_t getThingIndex(std::shared_ptr<Thing> thing) const override; + int32_t getThingIndex(const std::shared_ptr<Thing> &thing) const override; size_t getFirstIndex() const override; size_t getLastIndex() const override; uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const override; - void stashContainer(StashContainerList itemDict); + void stashContainer(const StashContainerList &itemDict); ItemsTierCountList getInventoryItemsId(bool ignoreStoreInbox = false) const; // This function is a override function of base class @@ -2723,17 +1327,17 @@ class Player final : public Creature, public Cylinder, public Bankable { // Function from player class with correct type sizes (uint16_t) std::map<uint16_t, uint16_t> &getAllSaleItemIdAndCount(std::map<uint16_t, uint16_t> &countMap) const; void getAllItemTypeCountAndSubtype(std::map<uint32_t, uint32_t> &countMap) const; - std::shared_ptr<Item> getForgeItemFromId(uint16_t itemId, uint8_t tier); + std::shared_ptr<Item> getForgeItemFromId(uint16_t itemId, uint8_t tier) const; std::shared_ptr<Thing> getThing(size_t index) const override; - void internalAddThing(std::shared_ptr<Thing> thing) override; - void internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void internalAddThing(const std::shared_ptr<Thing> &thing) override; + void internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; void addHuntingTaskKill(const std::shared_ptr<MonsterType> &mType); void addBestiaryKill(const std::shared_ptr<MonsterType> &mType); void addBosstiaryKill(const std::shared_ptr<MonsterType> &mType); - phmap::flat_hash_set<uint32_t> attackedSet; + phmap::flat_hash_set<uint32_t> attackedSet {}; std::map<uint8_t, OpenContainer> openContainers; std::map<uint32_t, std::shared_ptr<DepotLocker>> depotLockerMap; @@ -2742,12 +1346,6 @@ class Player final : public Creature, public Cylinder, public Bankable { std::map<uint32_t, int32_t> storageMap; std::map<uint16_t, uint64_t> itemPriceMap; - std::map<uint8_t, uint16_t> maxValuePerSkill = { - { SKILL_LIFE_LEECH_CHANCE, 100 }, - { SKILL_MANA_LEECH_CHANCE, 100 }, - { SKILL_CRITICAL_HIT_CHANCE, 100 * g_configManager().getNumber(CRITICALCHANCE) } - }; - std::map<uint64_t, std::shared_ptr<Reward>> rewardMap; std::map<ObjectCategory_t, std::pair<std::shared_ptr<Container>, std::shared_ptr<Container>>> m_managedContainers; @@ -2827,7 +1425,7 @@ class Player final : public Creature, public Cylinder, public Bankable { std::shared_ptr<Npc> shopOwner = nullptr; std::shared_ptr<Party> m_party = nullptr; std::shared_ptr<Player> tradePartner = nullptr; - ProtocolGame_ptr client; + std::shared_ptr<ProtocolGame> client = nullptr; std::shared_ptr<Task> walkTask; std::shared_ptr<Town> town; std::shared_ptr<Vocation> vocation = nullptr; @@ -2927,7 +1525,7 @@ class Player final : public Creature, public Cylinder, public Bankable { TradeState_t tradeState = TRADE_NONE; FightMode_t fightMode = FIGHTMODE_ATTACK; Faction_t faction = FACTION_PLAYER; - QuickLootFilter_t quickLootFilter; + QuickLootFilter_t quickLootFilter {}; PlayerPronoun_t pronoun = PLAYERPRONOUN_THEY; bool chaseMode = false; @@ -2971,37 +1569,11 @@ class Player final : public Creature, public Cylinder, public Bankable { uint16_t getStepSpeed() const override { return std::max<uint16_t>(PLAYER_MIN_SPEED, std::min<uint16_t>(PLAYER_MAX_SPEED, getSpeed())); } - void updateBaseSpeed() { - if (baseSpeed >= PLAYER_MAX_SPEED) { - return; - } - - if (!hasFlag(PlayerFlags_t::SetMaxSpeed)) { - baseSpeed = static_cast<uint16_t>(vocation->getBaseSpeed() + (level - 1)); - } else { - baseSpeed = PLAYER_MAX_SPEED; - } - } + void updateBaseSpeed(); bool isPromoted() const; - uint32_t getAttackSpeed() const { - bool onFistAttackSpeed = g_configManager().getBoolean(TOGGLE_ATTACK_SPEED_ONFIST); - uint32_t MAX_ATTACK_SPEED = g_configManager().getNumber(MAX_SPEED_ATTACKONFIST); - if (onFistAttackSpeed) { - uint32_t baseAttackSpeed = vocation->getAttackSpeed(); - uint32_t skillLevel = getSkillLevel(SKILL_FIST); - uint32_t attackSpeed = baseAttackSpeed - (skillLevel * g_configManager().getNumber(MULTIPLIER_ATTACKONFIST)); - - if (attackSpeed < MAX_ATTACK_SPEED) { - attackSpeed = MAX_ATTACK_SPEED; - } - - return static_cast<uint32_t>(attackSpeed); - } else { - return vocation->getAttackSpeed(); - } - } + uint32_t getAttackSpeed() const; static double_t getPercentLevel(uint64_t count, uint64_t nextLevelCount); double getLostPercent() const; @@ -3010,7 +1582,6 @@ class Player final : public Creature, public Cylinder, public Bankable { } bool isSuppress(ConditionType_t conditionType, bool attackerPlayer) const override; - void addConditionSuppression(const std::array<ConditionType_t, ConditionType_t::CONDITION_COUNT> &addConditions); uint16_t getLookCorpse() const override; void getPathSearchParams(const std::shared_ptr<Creature> &creature, FindPathParams &fpp) override; @@ -3066,13 +1637,13 @@ class Player final : public Creature, public Cylinder, public Bankable { std::array<double_t, COMBAT_COUNT> getFinalDamageReduction() const; void calculateDamageReductionFromEquipedItems(std::array<double_t, COMBAT_COUNT> &combatReductionMap) const; - void calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionMap, std::shared_ptr<Item> item) const; - void updateDamageReductionFromItemImbuement(std::array<double_t, COMBAT_COUNT> &combatReductionMap, std::shared_ptr<Item> item, uint16_t combatTypeIndex) const; - void updateDamageReductionFromItemAbility(std::array<double_t, COMBAT_COUNT> &combatReductionMap, std::shared_ptr<Item> item, uint16_t combatTypeIndex) const; + void calculateDamageReductionFromItem(std::array<double_t, COMBAT_COUNT> &combatReductionMap, const std::shared_ptr<Item> &item) const; + void updateDamageReductionFromItemImbuement(std::array<double_t, COMBAT_COUNT> &combatReductionMap, const std::shared_ptr<Item> &item, uint16_t combatTypeIndex) const; + void updateDamageReductionFromItemAbility(std::array<double_t, COMBAT_COUNT> &combatReductionMap, const std::shared_ptr<Item> &item, uint16_t combatTypeIndex) const; double_t calculateDamageReduction(double_t currentTotal, int16_t resistance) const; void removeEmptyRewards(); - bool hasOtherRewardContainerOpen(const std::shared_ptr<Container> container) const; + bool hasOtherRewardContainerOpen(const std::shared_ptr<Container> &container) const; void checkAndShowBlessingMessage(); diff --git a/src/creatures/players/storages/storages.cpp b/src/creatures/players/storages/storages.cpp index 6f6847858ed..64aab5e44d5 100644 --- a/src/creatures/players/storages/storages.cpp +++ b/src/creatures/players/storages/storages.cpp @@ -10,6 +10,11 @@ #include "creatures/players/storages/storages.hpp" #include "config/configmanager.hpp" +#include "lib/di/container.hpp" + +Storages &Storages::getInstance() { + return inject<Storages>(); +} bool Storages::loadFromXML() { pugi::xml_document doc; @@ -25,12 +30,12 @@ bool Storages::loadFromXML() { std::vector<std::pair<uint32_t, uint32_t>> ranges; - for (pugi::xml_node range : doc.child("storages").children("range")) { + for (const auto &range : doc.child("storages").children("range")) { uint32_t start = range.attribute("start").as_uint(); uint32_t end = range.attribute("end").as_uint(); - for (const auto &existingRange : ranges) { - if ((start >= existingRange.first && start <= existingRange.second) || (end >= existingRange.first && end <= existingRange.second)) { + for (const auto &[rangeStart, rangeEnd] : ranges) { + if ((start >= rangeStart && start <= rangeEnd) || (end >= rangeStart && end <= rangeEnd)) { g_logger().warn("[{}] Storage range from {} to {} conflicts with a previously defined range", __func__, start, end); continue; } @@ -38,11 +43,11 @@ bool Storages::loadFromXML() { ranges.emplace_back(start, end); - for (pugi::xml_node storage : range.children("storage")) { + for (const auto &storage : range.children("storage")) { std::string name = storage.attribute("name").as_string(); uint32_t key = storage.attribute("key").as_uint(); - for (char c : name) { + for (const char &c : name) { if (std::isupper(c)) { g_logger().warn("[{}] Storage from storages.xml with name: {}, contains uppercase letters. Please use dot notation pattern", __func__, name); break; diff --git a/src/creatures/players/storages/storages.hpp b/src/creatures/players/storages/storages.hpp index afc9fe14f90..70e099988fd 100644 --- a/src/creatures/players/storages/storages.hpp +++ b/src/creatures/players/storages/storages.hpp @@ -9,8 +9,6 @@ #pragma once -#include "lib/di/container.hpp" - class Storages { public: Storages() = default; @@ -19,9 +17,7 @@ class Storages { Storages(const Storages &) = delete; void operator=(const Storages &) = delete; - static Storages &getInstance() { - return inject<Storages>(); - } + static Storages &getInstance(); bool loadFromXML(); diff --git a/src/creatures/players/vip/player_vip.cpp b/src/creatures/players/vip/player_vip.cpp index 9d7bb7c27c7..8a64aebcf85 100644 --- a/src/creatures/players/vip/player_vip.cpp +++ b/src/creatures/players/vip/player_vip.cpp @@ -9,10 +9,11 @@ #include "creatures/players/vip/player_vip.hpp" -#include "io/iologindata.hpp" - -#include "game/game.hpp" +#include "account/account.hpp" +#include "creatures/players/grouping/groups.hpp" #include "creatures/players/player.hpp" +#include "io/iologindata.hpp" +#include "server/network/protocol/protocolgame.hpp" const uint8_t PlayerVIP::firstID = 1; const uint8_t PlayerVIP::lastID = 8; @@ -23,7 +24,8 @@ PlayerVIP::PlayerVIP(Player &player) : size_t PlayerVIP::getMaxEntries() const { if (m_player.group && m_player.group->maxVipEntries != 0) { return m_player.group->maxVipEntries; - } else if (m_player.isPremium()) { + } + if (m_player.isPremium()) { return 100; } return 20; @@ -36,7 +38,7 @@ uint8_t PlayerVIP::getMaxGroupEntries() const { return 0; } -void PlayerVIP::notifyStatusChange(std::shared_ptr<Player> loginPlayer, VipStatus_t status, bool message) const { +void PlayerVIP::notifyStatusChange(const std::shared_ptr<Player> &loginPlayer, VipStatus_t vipStatus, bool message) const { if (!m_player.client) { return; } @@ -45,12 +47,12 @@ void PlayerVIP::notifyStatusChange(std::shared_ptr<Player> loginPlayer, VipStatu return; } - m_player.client->sendUpdatedVIPStatus(loginPlayer->getGUID(), status); + m_player.client->sendUpdatedVIPStatus(loginPlayer->getGUID(), vipStatus); if (message) { - if (status == VipStatus_t::Online) { + if (vipStatus == VipStatus_t::Online) { m_player.sendTextMessage(TextMessage(MESSAGE_FAILURE, fmt::format("{} has logged in.", loginPlayer->getName()))); - } else if (status == VipStatus_t::Offline) { + } else if (vipStatus == VipStatus_t::Offline) { m_player.sendTextMessage(TextMessage(MESSAGE_FAILURE, fmt::format("{} has logged out.", loginPlayer->getName()))); } } @@ -99,8 +101,8 @@ bool PlayerVIP::addInternal(uint32_t vipGuid) { return vipGuids.insert(vipGuid).second; } -bool PlayerVIP::edit(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify, std::vector<uint8_t> groupsId) const { - const auto it = vipGuids.find(vipGuid); +bool PlayerVIP::edit(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify, const std::vector<uint8_t> &groupsId) const { + auto it = vipGuids.find(vipGuid); if (it == vipGuids.end()) { return false; // player is not in VIP } @@ -111,7 +113,7 @@ bool PlayerVIP::edit(uint32_t vipGuid, const std::string &description, uint32_t IOLoginData::removeGuidVIPGroupEntry(m_player.account->getID(), vipGuid); - for (const auto groupId : groupsId) { + for (const auto &groupId : groupsId) { const auto &group = getGroupByID(groupId); if (group) { group->vipGroupGuids.insert(vipGuid); @@ -123,7 +125,7 @@ bool PlayerVIP::edit(uint32_t vipGuid, const std::string &description, uint32_t } std::shared_ptr<VIPGroup> PlayerVIP::getGroupByID(uint8_t groupId) const { - auto it = std::find_if(vipGroups.begin(), vipGroups.end(), [groupId](const std::shared_ptr<VIPGroup> vipGroup) { + auto it = std::ranges::find_if(vipGroups, [groupId](const auto &vipGroup) { return vipGroup->id == groupId; }); @@ -132,7 +134,7 @@ std::shared_ptr<VIPGroup> PlayerVIP::getGroupByID(uint8_t groupId) const { std::shared_ptr<VIPGroup> PlayerVIP::getGroupByName(const std::string &name) const { const auto groupName = name.c_str(); - auto it = std::find_if(vipGroups.begin(), vipGroups.end(), [groupName](const std::shared_ptr<VIPGroup> vipGroup) { + auto it = std::ranges::find_if(vipGroups, [groupName](const auto &vipGroup) { return strcmp(groupName, vipGroup->name.c_str()) == 0; }); @@ -155,7 +157,7 @@ void PlayerVIP::addGroupInternal(uint8_t groupId, const std::string &name, bool } void PlayerVIP::removeGroup(uint8_t groupId) { - auto it = std::find_if(vipGroups.begin(), vipGroups.end(), [groupId](const std::shared_ptr<VIPGroup> vipGroup) { + auto it = std::ranges::find_if(vipGroups, [groupId](const auto &vipGroup) { return vipGroup->id == groupId; }); @@ -186,7 +188,7 @@ void PlayerVIP::addGroup(const std::string &name, bool customizable /*= true */) return; } - std::shared_ptr<VIPGroup> vipGroup = std::make_shared<VIPGroup>(freeId, name, customizable); + auto vipGroup = std::make_shared<VIPGroup>(freeId, name, customizable); vipGroups.emplace_back(vipGroup); if (m_player.account) { @@ -198,7 +200,7 @@ void PlayerVIP::addGroup(const std::string &name, bool customizable /*= true */) } } -void PlayerVIP::editGroup(uint8_t groupId, const std::string &newName, bool customizable /*= true*/) { +void PlayerVIP::editGroup(uint8_t groupId, const std::string &newName, bool customizable /*= true*/) const { if (getGroupByName(newName) != nullptr) { m_player.sendCancelMessage("A group with this name already exists. Please choose another name."); return; @@ -227,7 +229,7 @@ uint8_t PlayerVIP::getFreeId() const { return 0; } -const std::vector<uint8_t> PlayerVIP::getGroupsIdGuidBelongs(uint32_t guid) { +std::vector<uint8_t> PlayerVIP::getGroupsIdGuidBelongs(uint32_t guid) const { std::vector<uint8_t> guidBelongs; for (const auto &vipGroup : vipGroups) { if (vipGroup->vipGroupGuids.contains(guid)) { @@ -237,7 +239,7 @@ const std::vector<uint8_t> PlayerVIP::getGroupsIdGuidBelongs(uint32_t guid) { return guidBelongs; } -void PlayerVIP::addGuidToGroupInternal(uint8_t groupId, uint32_t guid) { +void PlayerVIP::addGuidToGroupInternal(uint8_t groupId, uint32_t guid) const { const auto &group = getGroupByID(groupId); if (group) { group->vipGroupGuids.insert(guid); diff --git a/src/creatures/players/vip/player_vip.hpp b/src/creatures/players/vip/player_vip.hpp index e9aeaf85326..0eb46b076af 100644 --- a/src/creatures/players/vip/player_vip.hpp +++ b/src/creatures/players/vip/player_vip.hpp @@ -13,18 +13,19 @@ class Player; -struct VIPGroup { +class VIPGroup { +public: uint8_t id = 0; - std::string name = ""; + std::string name; bool customizable = false; phmap::flat_hash_set<uint32_t> vipGroupGuids; VIPGroup() = default; - VIPGroup(uint8_t id, const std::string &name, bool customizable) : + VIPGroup(uint8_t id, std::string name, bool customizable) : id(id), name(std::move(name)), customizable(customizable) { } }; -class PlayerVIP { +class PlayerVIP { public: explicit PlayerVIP(Player &player); @@ -41,11 +42,11 @@ class PlayerVIP { status = newStatus; } - void notifyStatusChange(std::shared_ptr<Player> loginPlayer, VipStatus_t status, bool message = true) const; + void notifyStatusChange(const std::shared_ptr<Player> &loginPlayer, VipStatus_t status, bool message = true) const; bool remove(uint32_t vipGuid); bool add(uint32_t vipGuid, const std::string &vipName, VipStatus_t status); bool addInternal(uint32_t vipGuid); - bool edit(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify, std::vector<uint8_t> groupsId) const; + bool edit(uint32_t vipGuid, const std::string &description, uint32_t icon, bool notify, const std::vector<uint8_t> &groupsId) const; // VIP Group std::shared_ptr<VIPGroup> getGroupByID(uint8_t groupId) const; @@ -54,12 +55,12 @@ class PlayerVIP { void addGroupInternal(uint8_t groupId, const std::string &name, bool customizable); void removeGroup(uint8_t groupId); void addGroup(const std::string &name, bool customizable = true); - void editGroup(uint8_t groupId, const std::string &newName, bool customizable = true); + void editGroup(uint8_t groupId, const std::string &newName, bool customizable = true) const; - void addGuidToGroupInternal(uint8_t groupId, uint32_t guid); + void addGuidToGroupInternal(uint8_t groupId, uint32_t guid) const; uint8_t getFreeId() const; - const std::vector<uint8_t> getGroupsIdGuidBelongs(uint32_t guid); + std::vector<uint8_t> getGroupsIdGuidBelongs(uint32_t guid) const; [[nodiscard]] const std::vector<std::shared_ptr<VIPGroup>> &getGroups() const { return vipGroups; diff --git a/src/creatures/players/vocations/vocation.cpp b/src/creatures/players/vocations/vocation.cpp index 0217cabe7db..f36494895f5 100644 --- a/src/creatures/players/vocations/vocation.cpp +++ b/src/creatures/players/vocations/vocation.cpp @@ -9,6 +9,9 @@ #include "creatures/players/vocations/vocation.hpp" +#include "config/configmanager.hpp" +#include "items/item.hpp" +#include "lib/di/container.hpp" #include "utils/pugicast.hpp" #include "utils/tools.hpp" #include "enums/player_wheel.hpp" @@ -18,6 +21,10 @@ bool Vocations::reload() { return loadFromXml(); } +Vocations &Vocations::getInstance() { + return inject<Vocations>(); +} + bool Vocations::loadFromXml() { pugi::xml_document doc; auto folder = g_configManager().getString(CORE_DIRECTORY) + "/XML/vocations.xml"; @@ -27,17 +34,17 @@ bool Vocations::loadFromXml() { return false; } - for (auto vocationNode : doc.child("vocations").children()) { + for (const auto &vocationNode : doc.child("vocations").children()) { pugi::xml_attribute attr; - if (!(attr = vocationNode.attribute("id"))) { + if (!((attr = vocationNode.attribute("id")))) { g_logger().warn("[{}] - Missing vocation id", __FUNCTION__); continue; } - uint16_t id = pugi::cast<uint16_t>(attr.value()); + auto id = pugi::cast<uint16_t>(attr.value()); - auto res = vocationsMap.emplace(std::piecewise_construct, std::forward_as_tuple(id), std::forward_as_tuple(std::make_shared<Vocation>(id))); - auto voc = res.first->second; + auto [fst, snd] = vocationsMap.emplace(std::piecewise_construct, std::forward_as_tuple(id), std::forward_as_tuple(std::make_shared<Vocation>(id))); + const auto voc = fst->second; if ((attr = vocationNode.attribute("name"))) { voc->name = attr.as_string(); @@ -119,11 +126,11 @@ bool Vocations::loadFromXml() { voc->avatarLookType = pugi::cast<uint16_t>(attr.value()); } - for (auto childNode : vocationNode.children()) { + for (const auto &childNode : vocationNode.children()) { if (strcasecmp(childNode.name(), "skill") == 0) { pugi::xml_attribute skillIdAttribute = childNode.attribute("id"); if (skillIdAttribute) { - uint16_t skill_id = pugi::cast<uint16_t>(skillIdAttribute.value()); + auto skill_id = pugi::cast<uint16_t>(skillIdAttribute.value()); if (skill_id <= SKILL_LAST) { voc->skillMultipliers[skill_id] = pugi::cast<float>(childNode.attribute("multiplier").value()); } else { @@ -185,7 +192,7 @@ bool Vocations::loadFromXml() { pugi::xml_attribute qualityAttr = childNode.attribute("quality"); pugi::xml_attribute nameAttr = childNode.attribute("name"); auto quality = pugi::cast<uint8_t>(qualityAttr.value()); - auto name = nameAttr.as_string(); + const auto name = nameAttr.as_string(); voc->wheelGems[static_cast<WheelGemQuality_t>(quality)] = name; } } @@ -204,26 +211,38 @@ std::shared_ptr<Vocation> Vocations::getVocation(uint16_t id) { return it->second; } +const std::map<uint16_t, std::shared_ptr<Vocation>> &Vocations::getVocations() const { + return vocationsMap; +} + uint16_t Vocations::getVocationId(const std::string &name) const { - for (const auto &it : vocationsMap) { - if (strcasecmp(it.second->name.c_str(), name.c_str()) == 0) { - return it.first; + for (const auto &[vocationId, vocationPtr] : vocationsMap) { + if (caseInsensitiveCompare(vocationPtr->name, name)) { + return vocationId; } } - return -1; + return VOCATION_NONE; } uint16_t Vocations::getPromotedVocation(uint16_t vocationId) const { - for (const auto &it : vocationsMap) { - if (it.second->fromVocation == vocationId && it.first != vocationId) { - return it.first; + for (const auto &[currentVocationId, vocationPtr] : vocationsMap) { + if (vocationPtr->fromVocation == vocationId && currentVocationId != vocationId) { + return currentVocationId; } } return VOCATION_NONE; } uint32_t Vocation::skillBase[SKILL_LAST + 1] = { 50, 50, 50, 50, 30, 100, 20 }; -const uint16_t minSkillLevel = 10; +constexpr uint16_t minSkillLevel = 10; + +const std::string &Vocation::getVocName() const { + return name; +} + +const std::string &Vocation::getVocDescription() const { + return description; +} absl::uint128 Vocation::getTotalSkillTries(uint8_t skill, uint16_t level) { if (skill > SKILL_LAST) { @@ -253,7 +272,7 @@ uint64_t Vocation::getReqSkillTries(uint8_t skill, uint16_t level) { return it->second; } - uint64_t tries = static_cast<uint64_t>(skillBase[skill] * std::pow(static_cast<double>(skillMultipliers[skill]), level - (minSkillLevel + 1))); + const auto tries = static_cast<uint64_t>(skillBase[skill] * std::pow(static_cast<double>(skillMultipliers[skill]), level - (minSkillLevel + 1))); cacheSkill[skill][level] = tries; return tries; } @@ -282,26 +301,111 @@ uint64_t Vocation::getReqMana(uint32_t magLevel) { return it->second; } - uint64_t reqMana = std::floor<uint64_t>(1600 * std::pow<double>(manaMultiplier, static_cast<int32_t>(magLevel) - 1)); + const uint64_t reqMana = std::floor<uint64_t>(1600 * std::pow<double>(manaMultiplier, static_cast<int32_t>(magLevel) - 1)); cacheMana[magLevel] = reqMana; return reqMana; } +uint16_t Vocation::getId() const { + return id; +} + +uint8_t Vocation::getClientId() const { + return clientId; +} + +uint8_t Vocation::getBaseId() const { + return baseId; +} + +uint16_t Vocation::getAvatarLookType() const { + return avatarLookType; +} + +uint32_t Vocation::getHPGain() const { + return gainHP; +} + +uint32_t Vocation::getManaGain() const { + return gainMana; +} + +uint32_t Vocation::getCapGain() const { + return gainCap; +} + +uint32_t Vocation::getManaGainTicks() const { + return gainManaTicks / g_configManager().getFloat(RATE_MANA_REGEN_SPEED); +} + +uint32_t Vocation::getManaGainAmount() const { + return gainManaAmount * g_configManager().getFloat(RATE_MANA_REGEN); +} + +uint32_t Vocation::getHealthGainTicks() const { + return gainHealthTicks / g_configManager().getFloat(RATE_HEALTH_REGEN_SPEED); +} + +uint32_t Vocation::getHealthGainAmount() const { + return gainHealthAmount * g_configManager().getFloat(RATE_HEALTH_REGEN); +} + +uint8_t Vocation::getSoulMax() const { + return soulMax; +} + +uint32_t Vocation::getSoulGainTicks() const { + return gainSoulTicks / g_configManager().getFloat(RATE_SOUL_REGEN_SPEED); +} + +uint32_t Vocation::getBaseAttackSpeed() const { + return attackSpeed; +} + +uint32_t Vocation::getAttackSpeed() const { + return attackSpeed / g_configManager().getFloat(RATE_ATTACK_SPEED); +} + +uint32_t Vocation::getBaseSpeed() const { + return baseSpeed; +} + +uint32_t Vocation::getFromVocation() const { + return fromVocation; +} + +bool Vocation::getMagicShield() const { + return magicShield; +} + +bool Vocation::canCombat() const { + return combat; +} + std::vector<WheelGemSupremeModifier_t> Vocation::getSupremeGemModifiers() { if (!m_supremeGemModifiers.empty()) { return m_supremeGemModifiers; } - auto baseVocation = g_vocations().getVocation(getBaseId()); + const auto baseVocation = g_vocations().getVocation(getBaseId()); auto vocationName = asLowerCaseString(baseVocation->getVocName()); auto allModifiers = magic_enum::enum_entries<WheelGemSupremeModifier_t>(); g_logger().debug("Loading supreme gem modifiers for vocation: {}", vocationName); + for (const auto &[value, modifierName] : allModifiers) { std::string targetVocation(modifierName.substr(0, modifierName.find('_'))); toLowerCaseString(targetVocation); g_logger().debug("Checking supreme gem modifier: {}, targetVocation: {}", modifierName, targetVocation); if (targetVocation == "general" || targetVocation.find(vocationName) != std::string::npos) { - m_supremeGemModifiers.push_back(value); + m_supremeGemModifiers.emplace_back(value); } } return m_supremeGemModifiers; } + +uint16_t Vocation::getWheelGemId(WheelGemQuality_t quality) { + if (!wheelGems.contains(quality)) { + return 0; + } + const auto &gemName = wheelGems[quality]; + return Item::items.getItemIdByName(gemName); +} diff --git a/src/creatures/players/vocations/vocation.hpp b/src/creatures/players/vocations/vocation.hpp index 6bd8d9a2ebc..21a4ea79710 100644 --- a/src/creatures/players/vocations/vocation.hpp +++ b/src/creatures/players/vocations/vocation.hpp @@ -9,9 +9,7 @@ #pragma once -#include "declarations.hpp" -#include "items/item.hpp" -#include "lib/di/container.hpp" +#include "creatures/creatures_definitions.hpp" enum class WheelGemQuality_t : uint8_t; enum class WheelGemSupremeModifier_t : uint8_t; @@ -21,89 +19,47 @@ class Vocation { explicit Vocation(uint16_t initId) : id(initId) { } - const std::string &getVocName() const { - return name; - } - const std::string &getVocDescription() const { - return description; - } + const std::string &getVocName() const; + const std::string &getVocDescription() const; absl::uint128 getTotalSkillTries(uint8_t skill, uint16_t level); uint64_t getReqSkillTries(uint8_t skill, uint16_t level); absl::uint128 getTotalMana(uint32_t magLevel); uint64_t getReqMana(uint32_t magLevel); - uint16_t getId() const { - return id; - } - - uint8_t getClientId() const { - return clientId; - } - - uint8_t getBaseId() const { - return baseId; - } - - uint16_t getAvatarLookType() const { - return avatarLookType; - } - - uint32_t getHPGain() const { - return gainHP; - } - uint32_t getManaGain() const { - return gainMana; - } - uint32_t getCapGain() const { - return gainCap; - } - - uint32_t getManaGainTicks() const { - return gainManaTicks / g_configManager().getFloat(RATE_MANA_REGEN_SPEED); - } - - uint32_t getManaGainAmount() const { - return gainManaAmount * g_configManager().getFloat(RATE_MANA_REGEN); - } - - uint32_t getHealthGainTicks() const { - return gainHealthTicks / g_configManager().getFloat(RATE_HEALTH_REGEN_SPEED); - } - - uint32_t getHealthGainAmount() const { - return gainHealthAmount * g_configManager().getFloat(RATE_HEALTH_REGEN); - } - - uint8_t getSoulMax() const { - return soulMax; - } - - uint32_t getSoulGainTicks() const { - return gainSoulTicks / g_configManager().getFloat(RATE_SOUL_REGEN_SPEED); - } - - uint32_t getBaseAttackSpeed() const { - return attackSpeed; - } - - uint32_t getAttackSpeed() const { - return attackSpeed / g_configManager().getFloat(RATE_ATTACK_SPEED); - } - - uint32_t getBaseSpeed() const { - return baseSpeed; - } - - uint32_t getFromVocation() const { - return fromVocation; - } - - bool getMagicShield() const { - return magicShield; - } - bool canCombat() const { - return combat; - } + uint16_t getId() const; + + uint8_t getClientId() const; + + uint8_t getBaseId() const; + + uint16_t getAvatarLookType() const; + + uint32_t getHPGain() const; + uint32_t getManaGain() const; + uint32_t getCapGain() const; + + uint32_t getManaGainTicks() const; + + uint32_t getManaGainAmount() const; + + uint32_t getHealthGainTicks() const; + + uint32_t getHealthGainAmount() const; + + uint8_t getSoulMax() const; + + uint32_t getSoulGainTicks() const; + + uint32_t getBaseAttackSpeed() const; + + uint32_t getAttackSpeed() const; + + uint32_t getBaseSpeed() const; + + uint32_t getFromVocation() const; + + bool getMagicShield() const; + bool canCombat() const; float meleeDamageMultiplier = 1.0f; float distDamageMultiplier = 1.0f; @@ -119,13 +75,7 @@ class Vocation { std::vector<WheelGemSupremeModifier_t> getSupremeGemModifiers(); - uint16_t getWheelGemId(WheelGemQuality_t quality) { - if (!wheelGems.contains(quality)) { - return 0; - } - const auto &name = wheelGems[quality]; - return Item::items.getItemIdByName(name); - } + uint16_t getWheelGemId(WheelGemQuality_t quality); private: friend class Vocations; @@ -176,17 +126,13 @@ class Vocations { Vocations(const Vocations &) = delete; void operator=(const Vocations &) = delete; - static Vocations &getInstance() { - return inject<Vocations>(); - } + static Vocations &getInstance(); bool loadFromXml(); bool reload(); std::shared_ptr<Vocation> getVocation(uint16_t id); - const std::map<uint16_t, std::shared_ptr<Vocation>> &getVocations() const { - return vocationsMap; - } + const std::map<uint16_t, std::shared_ptr<Vocation>> &getVocations() const; uint16_t getVocationId(const std::string &name) const; uint16_t getPromotedVocation(uint16_t vocationId) const; diff --git a/src/creatures/players/wheel/player_wheel.cpp b/src/creatures/players/wheel/player_wheel.cpp index b577e998651..165a43f0687 100644 --- a/src/creatures/players/wheel/player_wheel.cpp +++ b/src/creatures/players/wheel/player_wheel.cpp @@ -9,15 +9,23 @@ #include "creatures/players/wheel/player_wheel.hpp" -#include "enums/player_wheel.hpp" +#include "map/spectators.hpp" +#include "creatures/monsters/monster.hpp" #include "config/configmanager.hpp" -#include "io/io_wheel.hpp" -#include "game/game.hpp" -#include "server/network/message/networkmessage.hpp" -#include "creatures/players/player.hpp" +#include "creatures/combat/condition.hpp" #include "creatures/combat/spells.hpp" -#include "kv/kv.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/vocations/vocation.hpp" #include "creatures/players/wheel/wheel_gems.hpp" +#include "enums/player_wheel.hpp" +#include "game/game.hpp" +#include "io/io_wheel.hpp" +#include "kv/kv.hpp" +#include "kv/kv_definitions.hpp" +#include "server/network/message/networkmessage.hpp" +#include "server/network/protocol/protocolgame.hpp" + +std::array<int32_t, COMBAT_COUNT> m_resistance = { 0 }; const static std::vector<WheelGemBasicModifier_t> wheelGemBasicSlot1Allowed = { WheelGemBasicModifier_t::General_FireResistance, @@ -317,7 +325,7 @@ PlayerWheel::PlayerWheel(Player &initPlayer) : } bool PlayerWheel::canPlayerSelectPointOnSlot(WheelSlots_t slot, bool recursive) const { - auto playerPoints = getWheelPoints(); + const auto playerPoints = getWheelPoints(); // Green quadrant if (slot == WheelSlots_t::SLOT_GREEN_200) { if (playerPoints < 375u) { @@ -883,19 +891,22 @@ uint16_t PlayerWheel::getUnusedPoints() const { } bool PlayerWheel::getSpellAdditionalArea(const std::string &spellName) const { - auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); + const auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); if (stage == 0) { return false; } - auto vocationEnum = m_player.getPlayerVocationEnum(); + const auto vocationEnum = m_player.getPlayerVocationEnum(); if (vocationEnum == Vocation_t::VOCATION_KNIGHT_CIP) { return checkSpellArea(g_game().getIOWheel()->getWheelBonusData().spells.knight, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { return checkSpellArea(g_game().getIOWheel()->getWheelBonusData().spells.paladin, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { return checkSpellArea(g_game().getIOWheel()->getWheelBonusData().spells.druid, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { return checkSpellArea(g_game().getIOWheel()->getWheelBonusData().spells.sorcerer, spellName, stage); } @@ -903,19 +914,22 @@ bool PlayerWheel::getSpellAdditionalArea(const std::string &spellName) const { } int PlayerWheel::getSpellAdditionalTarget(const std::string &spellName) const { - auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); + const auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); if (stage == 0) { return 0; } - auto vocationEnum = m_player.getPlayerVocationEnum(); + const auto vocationEnum = m_player.getPlayerVocationEnum(); if (vocationEnum == Vocation_t::VOCATION_KNIGHT_CIP) { return checkSpellAdditionalTarget(g_game().getIOWheel()->getWheelBonusData().spells.knight, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { return checkSpellAdditionalTarget(g_game().getIOWheel()->getWheelBonusData().spells.paladin, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { return checkSpellAdditionalTarget(g_game().getIOWheel()->getWheelBonusData().spells.druid, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { return checkSpellAdditionalTarget(g_game().getIOWheel()->getWheelBonusData().spells.sorcerer, spellName, stage); } @@ -923,37 +937,79 @@ int PlayerWheel::getSpellAdditionalTarget(const std::string &spellName) const { } int PlayerWheel::getSpellAdditionalDuration(const std::string &spellName) const { - auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); + const auto stage = static_cast<uint8_t>(getSpellUpgrade(spellName)); if (stage == 0) { return 0; } - auto vocationEnum = m_player.getPlayerVocationEnum(); + const auto vocationEnum = m_player.getPlayerVocationEnum(); if (vocationEnum == Vocation_t::VOCATION_KNIGHT_CIP) { return checkSpellAdditionalDuration(g_game().getIOWheel()->getWheelBonusData().spells.knight, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_PALADIN_CIP) { return checkSpellAdditionalDuration(g_game().getIOWheel()->getWheelBonusData().spells.paladin, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { return checkSpellAdditionalDuration(g_game().getIOWheel()->getWheelBonusData().spells.druid, spellName, stage); - } else if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { + } + if (vocationEnum == Vocation_t::VOCATION_SORCERER_CIP) { return checkSpellAdditionalDuration(g_game().getIOWheel()->getWheelBonusData().spells.sorcerer, spellName, stage); } return 0; } +bool PlayerWheel::handleTwinBurstsCooldown(const std::shared_ptr<Player> &player, const std::string &spellName, int spellCooldown, int rateCooldown) const { + // Map of spell pairs for Twin Bursts + static const std::unordered_map<std::string, std::string> spellPairs = { + { "Terra Burst", "Ice Burst" }, + { "Ice Burst", "Terra Burst" } + }; + + auto it = spellPairs.find(spellName); + if (it != spellPairs.end()) { + const auto &spell = g_spells().getSpellByName(it->second); + if (spell) { + const auto spellId = spell->getSpellId(); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, spellCooldown / rateCooldown, 0, false, spellId); + return player->addCondition(condition); + } + } + + return false; +} + +bool PlayerWheel::handleBeamMasteryCooldown(const std::shared_ptr<Player> &player, const std::string &spellName, int spellCooldown, int rateCooldown) const { + static const std::unordered_map<std::string, std::string> spellPairs = { + { "Great Death Beam", "Great Energy Beam" }, + { "Great Energy Beam", "Great Death Beam" } + }; + + auto it = spellPairs.find(spellName); + if (it != spellPairs.end()) { + const auto &spell = g_spells().getSpellByName(it->second); + if (spell) { + const auto spellId = spell->getSpellId(); + const auto &condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, spellCooldown / rateCooldown, 0, false, spellId); + return player->addCondition(condition); + } + } + + return false; +} + void PlayerWheel::addPromotionScrolls(NetworkMessage &msg) const { std::vector<uint16_t> unlockedScrolls; - for (const auto &scroll : WheelOfDestinyPromotionScrolls) { + for (const auto &[itemId, name, extraPoints] : WheelOfDestinyPromotionScrolls) { const auto &scrollKv = m_player.kv()->scoped("wheel-of-destiny")->scoped("scrolls"); if (!scrollKv) { continue; } - auto scrollOpt = scrollKv->get(scroll.name); + const auto scrollOpt = scrollKv->get(name); if (scrollOpt && scrollOpt->get<bool>()) { - unlockedScrolls.push_back(scroll.itemId); + unlockedScrolls.emplace_back(itemId); } } @@ -973,7 +1029,7 @@ std::shared_ptr<KV> PlayerWheel::gemsGradeKV(WheelFragmentType_t type, uint8_t p uint8_t PlayerWheel::getGemGrade(WheelFragmentType_t type, uint8_t pos) const { uint8_t grade = 0; - auto gradeKV = gemsGradeKV(type, pos)->get("grade"); + const auto gradeKV = gemsGradeKV(type, pos)->get("grade"); if (gradeKV.has_value()) { grade = static_cast<uint8_t>(gradeKV->get<IntType>()); @@ -983,14 +1039,14 @@ uint8_t PlayerWheel::getGemGrade(WheelFragmentType_t type, uint8_t pos) const { std::vector<PlayerWheelGem> PlayerWheel::getRevealedGems() const { std::vector<PlayerWheelGem> unlockedGems; - auto unlockedGemUUIDs = gemsKV()->scoped("revealed")->keys(); + const auto unlockedGemUUIDs = gemsKV()->scoped("revealed")->keys(); if (unlockedGemUUIDs.empty()) { return unlockedGems; } std::vector<std::string> sortedUnlockedGemGUIDs; for (const auto &uuid : unlockedGemUUIDs) { - sortedUnlockedGemGUIDs.push_back(uuid); + sortedUnlockedGemGUIDs.emplace_back(uuid); } std::sort(sortedUnlockedGemGUIDs.begin(), sortedUnlockedGemGUIDs.end(), [](const std::string &a, const std::string &b) { @@ -1006,14 +1062,14 @@ std::vector<PlayerWheelGem> PlayerWheel::getRevealedGems() const { if (gem.uuid.empty()) { continue; } - unlockedGems.push_back(gem); + unlockedGems.emplace_back(gem); } return unlockedGems; } std::vector<PlayerWheelGem> PlayerWheel::getActiveGems() const { std::vector<PlayerWheelGem> activeGems; - for (auto affinity : magic_enum::enum_values<WheelGemAffinity_t>()) { + for (const auto &affinity : magic_enum::enum_values<WheelGemAffinity_t>()) { std::string key(magic_enum::enum_name(affinity)); auto uuidKV = gemsKV()->scoped("active")->get(key); if (!uuidKV.has_value()) { @@ -1028,7 +1084,7 @@ std::vector<PlayerWheelGem> PlayerWheel::getActiveGems() const { if (gem.uuid.empty()) { continue; } - activeGems.push_back(gem); + activeGems.emplace_back(gem); } return activeGems; } @@ -1069,7 +1125,7 @@ uint64_t PlayerWheel::getGemRevealCost(WheelGemQuality_t quality) { return static_cast<uint64_t>(g_configManager().getNumber(key)); } -void PlayerWheel::revealGem(WheelGemQuality_t quality) { +void PlayerWheel::revealGem(WheelGemQuality_t quality) const { uint16_t gemId = m_player.getVocation()->getWheelGemId(quality); if (gemId == 0) { g_logger().error("[{}] Failed to get gem id for quality {} and vocation {}", __FUNCTION__, fmt::underlying(quality), m_player.getVocation()->getVocName()); @@ -1088,7 +1144,7 @@ void PlayerWheel::revealGem(WheelGemQuality_t quality) { g_logger().error("[{}] Failed to remove gem with id {} from player with name {}", __FUNCTION__, gemId, m_player.getName()); return; } - auto supremeModifiers = m_player.getVocation()->getSupremeGemModifiers(); + const auto supremeModifiers = m_player.getVocation()->getSupremeGemModifiers(); PlayerWheelGem gem; gem.uuid = KV::generateUUID(); gem.locked = false; @@ -1127,7 +1183,7 @@ PlayerWheelGem PlayerWheel::getGem(const std::string &uuid) const { } uint16_t PlayerWheel::getGemIndex(const std::string &uuid) const { - auto gems = getRevealedGems(); + const auto gems = getRevealedGems(); for (uint16_t i = 0; i < gems.size(); ++i) { if (gems[i].uuid == uuid) { return i; @@ -1137,8 +1193,8 @@ uint16_t PlayerWheel::getGemIndex(const std::string &uuid) const { return 0xFF; } -void PlayerWheel::destroyGem(uint16_t index) { - auto gem = getGem(index); +void PlayerWheel::destroyGem(uint16_t index) const { + const auto gem = getGem(index); if (gem.locked) { g_logger().error("[{}] Player {} destroyed locked gem with index {}", std::source_location::current().function_name(), m_player.getName(), index); return; @@ -1175,7 +1231,7 @@ void PlayerWheel::destroyGem(uint16_t index) { if (greaterFragments > 0) { const auto &fragmentsItem = Item::CreateItem(ITEM_GREATER_FRAGMENT, greaterFragments); - auto returnValue = g_game().internalPlayerAddItem(m_player.getPlayer(), fragmentsItem, false, CONST_SLOT_BACKPACK); + auto returnValue = g_game().internalPlayerAddItem(m_player.getPlayer(), fragmentsItem, false, CONST_SLOT_WHEREEVER); if (returnValue != RETURNVALUE_NOERROR) { g_logger().error("Failed to add {} greater fragments to player with name {}", greaterFragments, m_player.getName()); m_player.sendCancelMessage(getReturnMessage(RETURNVALUE_CONTACTADMINISTRATOR)); @@ -1186,13 +1242,16 @@ void PlayerWheel::destroyGem(uint16_t index) { gem.remove(gemsKV()); - m_player.client->sendResourceBalance(RESOURCE_LESSER_FRAGMENT, m_player.getItemTypeCount(ITEM_LESSER_FRAGMENT)); - m_player.client->sendResourceBalance(RESOURCE_GREATER_FRAGMENT, m_player.getItemTypeCount(ITEM_GREATER_FRAGMENT)); + const auto totalLesserFragment = m_player.getItemTypeCount(ITEM_LESSER_FRAGMENT) + m_player.getStashItemCount(ITEM_LESSER_FRAGMENT); + const auto totalGreaterFragment = m_player.getItemTypeCount(ITEM_GREATER_FRAGMENT) + m_player.getStashItemCount(ITEM_GREATER_FRAGMENT); + + m_player.client->sendResourceBalance(RESOURCE_LESSER_FRAGMENT, totalLesserFragment); + m_player.client->sendResourceBalance(RESOURCE_GREATER_FRAGMENT, totalGreaterFragment); sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::switchGemDomain(uint16_t index) { +void PlayerWheel::switchGemDomain(uint16_t index) const { auto gem = getGem(index); if (gem.locked) { g_logger().error("[{}] Player {} trying to destroy locked gem with index {}", __FUNCTION__, m_player.getName(), index); @@ -1210,14 +1269,14 @@ void PlayerWheel::switchGemDomain(uint16_t index) { sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::toggleGemLock(uint16_t index) { +void PlayerWheel::toggleGemLock(uint16_t index) const { auto gem = getGem(index); gem.locked = !gem.locked; gem.save(gemsKV()); sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::setActiveGem(WheelGemAffinity_t affinity, uint16_t index) { +void PlayerWheel::setActiveGem(WheelGemAffinity_t affinity, uint16_t index) const { auto gem = getGem(index); if (gem.uuid.empty()) { g_logger().error("[{}] Failed to load gem with index {}", __FUNCTION__, index); @@ -1227,17 +1286,78 @@ void PlayerWheel::setActiveGem(WheelGemAffinity_t affinity, uint16_t index) { g_logger().error("[{}] Gem with index {} has affinity {} but trying to set it to {}", __FUNCTION__, index, fmt::underlying(gem.affinity), fmt::underlying(affinity)); return; } - std::string key(magic_enum::enum_name(affinity)); + const std::string key(magic_enum::enum_name(affinity)); gemsKV()->scoped("active")->set(key, gem.uuid); } -void PlayerWheel::removeActiveGem(WheelGemAffinity_t affinity) { - std::string key(magic_enum::enum_name(affinity)); +void PlayerWheel::removeActiveGem(WheelGemAffinity_t affinity) const { + const std::string key(magic_enum::enum_name(affinity)); gemsKV()->scoped("active")->remove(key); } +void PlayerWheel::addRevelationBonus(WheelGemAffinity_t affinity, uint16_t points) { + m_bonusRevelationPoints[static_cast<size_t>(affinity)] += points; +} + +void PlayerWheel::resetRevelationBonus() { + m_bonusRevelationPoints = { 0, 0, 0, 0 }; +} + +void PlayerWheel::addSpellBonus(const std::string &spellName, const WheelSpells::Bonus &bonus) { + if (m_spellsBonuses.contains(spellName)) { + m_spellsBonuses[spellName].decrease.cooldown += bonus.decrease.cooldown; + m_spellsBonuses[spellName].decrease.manaCost += bonus.decrease.manaCost; + m_spellsBonuses[spellName].decrease.secondaryGroupCooldown += bonus.decrease.secondaryGroupCooldown; + m_spellsBonuses[spellName].increase.aditionalTarget += bonus.increase.aditionalTarget; + m_spellsBonuses[spellName].increase.area = bonus.increase.area; + m_spellsBonuses[spellName].increase.criticalChance += bonus.increase.criticalChance; + m_spellsBonuses[spellName].increase.criticalDamage += bonus.increase.criticalDamage; + m_spellsBonuses[spellName].increase.damage += bonus.increase.damage; + m_spellsBonuses[spellName].increase.damageReduction += bonus.increase.damageReduction; + m_spellsBonuses[spellName].increase.duration += bonus.increase.duration; + m_spellsBonuses[spellName].increase.heal += bonus.increase.heal; + m_spellsBonuses[spellName].leech.life += bonus.leech.life; + m_spellsBonuses[spellName].leech.mana += bonus.leech.mana; + return; + } + m_spellsBonuses[spellName] = bonus; +} + +int32_t PlayerWheel::getSpellBonus(const std::string &spellName, WheelSpellBoost_t boost) const { + using enum WheelSpellBoost_t; + + if (!m_spellsBonuses.contains(spellName)) { + return 0; + } + const auto &[leech, increase, decrease] = m_spellsBonuses.at(spellName); + switch (boost) { + case COOLDOWN: + return decrease.cooldown; + case MANA: + return decrease.manaCost; + case SECONDARY_GROUP_COOLDOWN: + return decrease.secondaryGroupCooldown; + case CRITICAL_CHANCE: + return increase.criticalChance; + case CRITICAL_DAMAGE: + return increase.criticalDamage; + case DAMAGE: + return increase.damage; + case DAMAGE_REDUCTION: + return increase.damageReduction; + case HEAL: + return increase.heal; + case LIFE_LEECH: + return leech.life; + case MANA_LEECH: + return leech.mana; + default: + return 0; + } +} + void PlayerWheel::addGems(NetworkMessage &msg) const { - auto activeGems = getActiveGems(); + const auto activeGems = getActiveGems(); msg.addByte(activeGems.size()); g_logger().debug("[{}] Player {} has {} active gems", __FUNCTION__, m_player.getName(), activeGems.size()); for (const auto &gem : activeGems) { @@ -1246,7 +1366,7 @@ void PlayerWheel::addGems(NetworkMessage &msg) const { msg.add<uint16_t>(getGemIndex(gem.uuid)); } - auto revealedGems = getRevealedGems(); + const auto revealedGems = getRevealedGems(); msg.add<uint16_t>(revealedGems.size()); uint16_t index = 0; for (const auto &gem : revealedGems) { @@ -1328,8 +1448,13 @@ void PlayerWheel::improveGemGrade(WheelFragmentType_t fragmentType, uint8_t pos) return; } - if (!m_player.hasItemCountById(fragmentId, quantity, false)) { - g_logger().error("[{}] Player {} does not have the required {} fragments with id {}", __FUNCTION__, m_player.getName(), quantity, fragmentId); + if (value == 0 && quantity == 0) { + g_logger().error("[{}] Player {} trying to upgrade gem to grade greater than 3", std::source_location::current().function_name(), m_player.getName()); + return; + } + + if (!m_player.hasItemCountById(fragmentId, quantity, true)) { + g_logger().error("[{}] Player {} does not have the required {} fragments with id {}", std::source_location::current().function_name(), m_player.getName(), quantity, fragmentId); return; } @@ -1338,7 +1463,7 @@ void PlayerWheel::improveGemGrade(WheelFragmentType_t fragmentType, uint8_t pos) return; } - if (!m_player.removeItemCountById(fragmentId, quantity, false)) { + if (!m_player.removeItemCountById(fragmentId, quantity, true)) { g_logger().error("[{}] Failed to remove {} fragments with id {} from player {}", std::source_location::current().function_name(), quantity, fragmentId, m_player.getName()); return; } @@ -1357,7 +1482,7 @@ std::tuple<int, int> PlayerWheel::getLesserGradeCost(uint8_t grade) const { case 3: return std::make_tuple(30000000, 30); default: - throw std::invalid_argument("Invalid level for Lesser Fragment."); + return {}; } } @@ -1370,7 +1495,7 @@ std::tuple<int, int> PlayerWheel::getGreaterGradeCost(uint8_t grade) const { case 3: return std::make_tuple(75000000, 30); default: - throw std::invalid_argument("Invalid level for Greater Fragment."); + return {}; } } @@ -1380,8 +1505,7 @@ void PlayerWheel::sendOpenWheelWindow(NetworkMessage &msg, uint32_t ownerId) { } msg.addByte(0x5F); - bool canUse = canOpenWheel(); - + const bool canUse = canOpenWheel(); msg.add<uint32_t>(ownerId); // Player ID msg.addByte(canUse ? 1 : 0); // Can Use if (!canUse) { @@ -1400,15 +1524,23 @@ void PlayerWheel::sendOpenWheelWindow(NetworkMessage &msg, uint32_t ownerId) { addPromotionScrolls(msg); addGems(msg); addGradeModifiers(msg); - // TODO: read items from inventory - auto voc = m_player.getVocation(); + + const auto &voc = m_player.getVocation(); + if (!voc) { + g_logger().error("[{}] Failed to get vocation for player {}", __FUNCTION__, m_player.getName()); + return; + } + + const auto totalLesserFragment = m_player.getItemTypeCount(ITEM_LESSER_FRAGMENT) + m_player.getStashItemCount(ITEM_LESSER_FRAGMENT); + const auto totalGreaterFragment = m_player.getItemTypeCount(ITEM_GREATER_FRAGMENT) + m_player.getStashItemCount(ITEM_GREATER_FRAGMENT); + m_player.client->sendResourceBalance(RESOURCE_BANK, m_player.getBankBalance()); m_player.client->sendResourceBalance(RESOURCE_INVENTORY_MONEY, m_player.getMoney()); m_player.client->sendResourceBalance(RESOURCE_LESSER_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Lesser))); m_player.client->sendResourceBalance(RESOURCE_REGULAR_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Regular))); m_player.client->sendResourceBalance(RESOURCE_GREATER_GEMS, m_player.getItemTypeCount(voc->getWheelGemId(WheelGemQuality_t::Greater))); - m_player.client->sendResourceBalance(RESOURCE_LESSER_FRAGMENT, m_player.getItemTypeCount(ITEM_LESSER_FRAGMENT)); - m_player.client->sendResourceBalance(RESOURCE_GREATER_FRAGMENT, m_player.getItemTypeCount(ITEM_GREATER_FRAGMENT)); + m_player.client->sendResourceBalance(RESOURCE_LESSER_FRAGMENT, totalLesserFragment); + m_player.client->sendResourceBalance(RESOURCE_GREATER_FRAGMENT, totalGreaterFragment); } void PlayerWheel::sendGiftOfLifeCooldown() const { @@ -1440,7 +1572,7 @@ bool PlayerWheel::checkSavePointsBySlotType(WheelSlots_t slotType, uint16_t poin setPointsBySlotType(static_cast<uint8_t>(slotType), 0); - auto unusedPoints = getUnusedPoints(); + const auto unusedPoints = getUnusedPoints(); if (points > unusedPoints) { return false; } @@ -1452,7 +1584,7 @@ bool PlayerWheel::checkSavePointsBySlotType(WheelSlots_t slotType, uint16_t poin void PlayerWheel::saveSlotPointsHandleRetryErrors(std::vector<SlotInfo> &retryTable, int &errors) { std::vector<SlotInfo> temporaryTable; for (const auto &data : retryTable) { - auto saved = checkSavePointsBySlotType(static_cast<WheelSlots_t>(data.slot), data.points); + const auto saved = checkSavePointsBySlotType(static_cast<WheelSlots_t>(data.slot), data.points); if (saved) { errors--; } else { @@ -1486,13 +1618,13 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) { return; } - auto order = g_game().getIOWheel()->getSlotPrioritaryOrder(static_cast<WheelSlots_t>(slot)); + const auto order = g_game().getIOWheel()->getSlotPrioritaryOrder(static_cast<WheelSlots_t>(slot)); if (order == -1) { continue; } // The slot information is then added to the vector in order. - sortedTable.push_back({ order, slot, slotPoints }); + sortedTable.emplace_back(order, slot, slotPoints); } // After iterating over all slots, the vector is sorted according to the slot order. @@ -1505,7 +1637,7 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) { // Processes the vector in the correct order. If it is not possible to save points for a slot, for (const auto &data : sortedTable) { - auto canSave = checkSavePointsBySlotType(static_cast<WheelSlots_t>(data.slot), data.points); + const auto canSave = checkSavePointsBySlotType(static_cast<WheelSlots_t>(data.slot), data.points); if (!canSave) { sortedTableRetry.emplace_back(data); errors++; @@ -1529,13 +1661,13 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) { } // Gem Vessels - for (auto affinity : magic_enum::enum_values<WheelGemAffinity_t>()) { - bool hasGem = msg.getByte(); + for (const auto &affinity : magic_enum::enum_values<WheelGemAffinity_t>()) { + const bool hasGem = msg.getByte(); if (!hasGem) { removeActiveGem(affinity); continue; } - uint16_t gemIndex = msg.get<uint16_t>(); + const auto gemIndex = msg.get<uint16_t>(); setActiveGem(affinity, gemIndex); } @@ -1550,14 +1682,14 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) { */ void PlayerWheel::loadDBPlayerSlotPointsOnLogin() { auto resultString = fmt::format("SELECT `slot` FROM `player_wheeldata` WHERE `player_id` = {}", m_player.getGUID()); - const DBResult_ptr &result = Database::getInstance().storeQuery(resultString); + const DBResult_ptr &result = g_database().storeQuery(resultString); // Ignore if player not have nothing inserted in the table if (!result) { return; } unsigned long size; - auto attribute = result->getStream("slot", size); + const auto attribute = result->getStream("slot", size); PropStream propStream; propStream.init(attribute, size); for (size_t i = 0; i < size; i++) { @@ -1571,17 +1703,12 @@ void PlayerWheel::loadDBPlayerSlotPointsOnLogin() { } bool PlayerWheel::saveDBPlayerSlotPointsOnLogout() const { - Database &db = Database::getInstance(); - std::ostringstream query; DBInsert insertWheelData("INSERT INTO `player_wheeldata` (`player_id`, `slot`) VALUES "); insertWheelData.upsert({ "slot" }); PropWriteStream stream; const auto wheelSlots = getSlots(); for (uint8_t i = 1; i < wheelSlots.size(); ++i) { auto value = wheelSlots[i]; - if (value == 0) { - continue; - } stream.write<uint8_t>(i); stream.write<uint16_t>(value); @@ -1591,7 +1718,7 @@ bool PlayerWheel::saveDBPlayerSlotPointsOnLogout() const { size_t attributesSize; const char* attributes = stream.getStream(attributesSize); if (attributesSize > 0) { - query << m_player.getGUID() << ',' << db.escapeBlob(attributes, (uint32_t)attributesSize); + const auto query = fmt::format("{}, {}", m_player.getGUID(), g_database().escapeBlob(attributes, static_cast<uint32_t>(attributesSize))); if (!insertWheelData.addRow(query)) { g_logger().debug("[{}] failed to insert row data", __FUNCTION__); return false; @@ -1613,15 +1740,19 @@ uint16_t PlayerWheel::getExtraPoints() const { } uint16_t totalBonus = 0; - for (const auto &scroll : WheelOfDestinyPromotionScrolls) { + for (const auto &[itemId, name, extraPoints] : WheelOfDestinyPromotionScrolls) { + if (itemId == 0) { + continue; + } + const auto &scrollKv = m_player.kv()->scoped("wheel-of-destiny")->scoped("scrolls"); if (!scrollKv) { continue; } - auto scrollKV = scrollKv->get(scroll.name); + const auto scrollKV = scrollKv->get(name); if (scrollKV && scrollKV->get<bool>()) { - totalBonus += scroll.extraPoints; + totalBonus += extraPoints; } } @@ -1629,7 +1760,7 @@ uint16_t PlayerWheel::getExtraPoints() const { } uint16_t PlayerWheel::getWheelPoints(bool includeExtraPoints /* = true*/) const { - uint32_t level = m_player.getLevel(); + const uint32_t level = m_player.getLevel(); auto totalPoints = std::max(0u, (level - m_minLevelToStartCountPoints)) * m_pointsPerLevel; if (includeExtraPoints) { @@ -1703,7 +1834,7 @@ uint8_t PlayerWheel::getOptions(uint32_t ownerId) const { // Check if is in the temple range (we assume the temple is within the range of 10 sqms) if (m_player.getZoneType() == ZONE_PROTECTION) { - for (auto [townid, town] : g_game().map.towns.getTowns()) { + for (const auto &[townid, town] : g_game().map.towns.getTowns()) { if (Position::areInRange<1, 10>(town->getTemplePosition(), m_player.getPosition())) { return 1; } @@ -1780,7 +1911,7 @@ void PlayerWheel::setPlayerCombatStats(CombatType_t type, int32_t leechAmount) { } } -void PlayerWheel::reloadPlayerData() { +void PlayerWheel::reloadPlayerData() const { // Maybe it's not really necessary, but it doesn't hurt to validate if (!m_player.getTile()) { return; @@ -1796,7 +1927,7 @@ void PlayerWheel::reloadPlayerData() { void PlayerWheel::registerPlayerBonusData() { addStat(WheelStat_t::HEALTH, m_playerBonusData.stats.health); addStat(WheelStat_t::MANA, m_playerBonusData.stats.mana); - addStat(WheelStat_t::CAPACITY, m_playerBonusData.stats.capacity * 100); + addStat(WheelStat_t::CAPACITY, m_playerBonusData.stats.capacity); addStat(WheelStat_t::MITIGATION, m_playerBonusData.mitigation * 100); addStat(WheelStat_t::DAMAGE, m_playerBonusData.stats.damage); addStat(WheelStat_t::HEALING, m_playerBonusData.stats.healing); @@ -1813,7 +1944,7 @@ void PlayerWheel::registerPlayerBonusData() { // Instant setSpellInstant("Battle Instinct", m_playerBonusData.instant.battleInstinct); setSpellInstant("Battle Healing", m_playerBonusData.instant.battleHealing); - setSpellInstant("Positional Tatics", m_playerBonusData.instant.positionalTatics); + setSpellInstant("Positional Tactics", m_playerBonusData.instant.positionalTactics); setSpellInstant("Ballistic Mastery", m_playerBonusData.instant.ballisticMastery); setSpellInstant("Healing Link", m_playerBonusData.instant.healingLink); setSpellInstant("Runic Mastery", m_playerBonusData.instant.runicMastery); @@ -1848,14 +1979,13 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.stages.divineEmpowerment; ++i) { setSpellInstant("Divine Empowerment", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 4 * 1000; + if (m_playerBonusData.stages.divineEmpowerment >= 2) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 4000; addSpellBonus("Divine Empowerment", bonus); } if (m_playerBonusData.stages.divineEmpowerment >= 3) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 4000; addSpellBonus("Divine Empowerment", bonus); } } else { @@ -1868,12 +1998,12 @@ void PlayerWheel::registerPlayerBonusData() { } if (m_playerBonusData.stages.divineGrenade >= 2) { WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 4000; + bonus.decrease.cooldown = 4 * 1000; addSpellBonus("Divine Grenade", bonus); } if (m_playerBonusData.stages.divineGrenade >= 3) { WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 6000; + bonus.decrease.cooldown = 6 * 1000; addSpellBonus("Divine Grenade", bonus); } } else { @@ -1888,9 +2018,21 @@ void PlayerWheel::registerPlayerBonusData() { setSpellInstant("Drain Body", false); } if (m_playerBonusData.stages.beamMastery > 0) { + m_beamMasterySpells.emplace("Energy Beam"); + m_beamMasterySpells.emplace("Great Death Beam"); + m_beamMasterySpells.emplace("Great Energy Beam"); for (int i = 0; i < m_playerBonusData.stages.beamMastery; ++i) { setSpellInstant("Beam Mastery", true); } + WheelSpells::Bonus deathBeamBonus; + deathBeamBonus.decrease.cooldown = 2 * 1000; + deathBeamBonus.increase.damage = 6; + if (m_playerBonusData.stages.beamMastery >= 2) { + addSpellBonus("Great Death Beam", deathBeamBonus); + } + if (m_playerBonusData.stages.beamMastery >= 3) { + addSpellBonus("Great Death Beam", deathBeamBonus); + } } else { setSpellInstant("Beam Mastery", false); } @@ -1899,6 +2041,17 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.stages.twinBurst; ++i) { setSpellInstant("Twin Burst", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 4 * 1000; + bonus.decrease.secondaryGroupCooldown = 4 * 1000; + if (m_playerBonusData.stages.twinBurst >= 2) { + addSpellBonus("Ice Burst", bonus); + addSpellBonus("Terra Burst", bonus); + } + if (m_playerBonusData.stages.twinBurst >= 3) { + addSpellBonus("Ice Burst", bonus); + addSpellBonus("Terra Burst", bonus); + } } else { setSpellInstant("Twin Burst", false); } @@ -1907,6 +2060,14 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.stages.executionersThrow; ++i) { setSpellInstant("Executioner's Throw", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 4 * 1000; + if (m_playerBonusData.stages.executionersThrow >= 2) { + addSpellBonus("Executioner's Throw", bonus); + } + if (m_playerBonusData.stages.executionersThrow >= 3) { + addSpellBonus("Executioner's Throw", bonus); + } } else { setSpellInstant("Executioner's Throw", false); } @@ -1916,14 +2077,13 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.avatar.light; ++i) { setSpellInstant("Avatar of Light", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes + if (m_playerBonusData.avatar.light >= 2) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Light", bonus); } if (m_playerBonusData.avatar.light >= 3) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Light", bonus); } } else { @@ -1934,14 +2094,13 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.avatar.nature; ++i) { setSpellInstant("Avatar of Nature", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes + if (m_playerBonusData.avatar.nature >= 2) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Nature", bonus); } if (m_playerBonusData.avatar.nature >= 3) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Nature", bonus); } } else { @@ -1952,14 +2111,12 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.avatar.steel; ++i) { setSpellInstant("Avatar of Steel", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes if (m_playerBonusData.avatar.steel >= 2) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Steel", bonus); } if (m_playerBonusData.avatar.steel >= 3) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Steel", bonus); } } else { @@ -1970,14 +2127,12 @@ void PlayerWheel::registerPlayerBonusData() { for (int i = 0; i < m_playerBonusData.avatar.storm; ++i) { setSpellInstant("Avatar of Storm", true); } + WheelSpells::Bonus bonus; + bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes if (m_playerBonusData.avatar.storm >= 2) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Storm", bonus); } if (m_playerBonusData.avatar.storm >= 3) { - WheelSpells::Bonus bonus; - bonus.decrease.cooldown = 30 * 60 * 1000; // 30 minutes addSpellBonus("Avatar of Storm", bonus); } } else { @@ -2041,12 +2196,12 @@ void PlayerWheel::printPlayerWheelMethodsBonusData(const PlayerWheelMethodsBonus g_logger().debug("Vessel Resonance:"); for (size_t i = 0; i < bonusData.unlockedVesselResonances.size(); ++i) { - auto count = bonusData.unlockedVesselResonances[i]; + const auto count = bonusData.unlockedVesselResonances[i]; if (count == 0) { continue; } - WheelGemAffinity_t affinity = static_cast<WheelGemAffinity_t>(i); + const auto affinity = static_cast<WheelGemAffinity_t>(i); std::string affinityName(magic_enum::enum_name(affinity)); g_logger().debug(" Affinity: {} count: {}", affinityName, bonusData.unlockedVesselResonances[i]); } @@ -2077,8 +2232,8 @@ void PlayerWheel::printPlayerWheelMethodsBonusData(const PlayerWheelMethodsBonus if (bonusData.instant.battleHealing) { g_logger().debug(" battleHealing: {}", bonusData.instant.battleHealing); } - if (bonusData.instant.positionalTatics) { - g_logger().debug(" positionalTatics: {}", bonusData.instant.positionalTatics); + if (bonusData.instant.positionalTactics) { + g_logger().debug(" positionalTactics: {}", bonusData.instant.positionalTactics); } if (bonusData.instant.ballisticMastery) { g_logger().debug(" ballisticMastery: {}", bonusData.instant.ballisticMastery); @@ -2144,10 +2299,10 @@ void PlayerWheel::printPlayerWheelMethodsBonusData(const PlayerWheelMethodsBonus g_logger().debug("mitigation: {}", bonusData.mitigation); } - auto &spellsVector = bonusData.spells; + const auto &spellsVector = bonusData.spells; if (!spellsVector.empty()) { g_logger().debug("Spells:"); - for (const auto &spell : bonusData.spells) { + for (const auto &spell : spellsVector) { g_logger().debug(" {}", spell); } } @@ -2157,14 +2312,14 @@ void PlayerWheel::printPlayerWheelMethodsBonusData(const PlayerWheelMethodsBonus void PlayerWheel::loadDedicationAndConvictionPerks() { using VocationBonusFunction = std::function<void(const std::shared_ptr<Player> &, uint16_t, uint8_t, PlayerWheelMethodsBonusData &)>; - auto wheelFunctions = g_game().getIOWheel()->getWheelMapFunctions(); - auto vocationCipId = m_player.getPlayerVocationEnum(); + const auto &wheelFunctions = g_game().getIOWheel()->getWheelMapFunctions(); + const auto vocationCipId = m_player.getPlayerVocationEnum(); if (vocationCipId < VOCATION_KNIGHT_CIP || vocationCipId > VOCATION_DRUID_CIP) { return; } for (uint8_t i = WheelSlots_t::SLOT_FIRST; i <= WheelSlots_t::SLOT_LAST; ++i) { - uint16_t points = getPointsBySlotType(static_cast<WheelSlots_t>(i)); + const uint16_t points = getPointsBySlotType(static_cast<WheelSlots_t>(i)); if (points > 0) { VocationBonusFunction internalData = nullptr; auto it = wheelFunctions.find(static_cast<WheelSlots_t>(i)); @@ -2222,7 +2377,7 @@ void PlayerWheel::processActiveGems() { if (count >= 3 && quality >= WheelGemQuality_t::Greater) { uint8_t grade = getGemGrade(WheelFragmentType_t::Greater, static_cast<uint8_t>(supremeModifier)); std::string modifierName(magic_enum::enum_name(supremeModifier)); - g_logger().info("[{}] Adding supreme modifier {} to player {} from {} gem affinity {}", __FUNCTION__, modifierName, playerName, magic_enum::enum_name(quality), magic_enum::enum_name(affinity)); + g_logger().debug("[{}] Adding supreme modifier {} to player {} from {} gem affinity {}", __FUNCTION__, modifierName, playerName, magic_enum::enum_name(quality), magic_enum::enum_name(affinity)); m_modifierContext->addStrategies(supremeModifier, grade); } } @@ -2244,7 +2399,7 @@ void PlayerWheel::applyStageBonusForColor(const std::string &color) { return; } - auto [statsDamage, statsHealing] = g_game().getIOWheel()->getRevelationStatByStage(stageEnum); + const auto &[statsDamage, statsHealing] = g_game().getIOWheel()->getRevelationStatByStage(stageEnum); m_playerBonusData.stats.damage += statsDamage; m_playerBonusData.stats.healing += statsHealing; @@ -2322,7 +2477,6 @@ void PlayerWheel::applyBlueStageBonus(uint8_t stageValue, Vocation_t vocationEnu } else if (vocationEnum == Vocation_t::VOCATION_DRUID_CIP) { m_playerBonusData.stages.twinBurst = stageValue; for (uint8_t i = 1; i <= stageValue; ++i) { - addSpellToVector("Twin Burst"); addSpellToVector("Terra Burst"); addSpellToVector("Ice Burst"); } @@ -2331,7 +2485,7 @@ void PlayerWheel::applyBlueStageBonus(uint8_t stageValue, Vocation_t vocationEnu WheelStageEnum_t PlayerWheel::getPlayerSliceStage(const std::string &color) const { std::vector<WheelSlots_t> slots; - WheelGemAffinity_t affinity = WheelGemAffinity_t::Green; + auto affinity = WheelGemAffinity_t::Green; if (color == "green") { affinity = WheelGemAffinity_t::Green; slots = { @@ -2406,7 +2560,7 @@ WheelStageEnum_t PlayerWheel::getPlayerSliceStage(const std::string &color) cons const auto modsSupremeIt = modsSupremePositionByVocation.find(vocationBaseId); if (modsSupremeIt != modsSupremePositionByVocation.end()) { - for (auto modPosition : modsSupremeIt->second.get()) { + for (const auto &modPosition : modsSupremeIt->second.get()) { const auto pos = static_cast<uint8_t>(modPosition); uint8_t grade = 0; auto gradeKV = gemsGradeKV(WheelFragmentType_t::Greater, pos)->get("grade"); @@ -2423,9 +2577,11 @@ WheelStageEnum_t PlayerWheel::getPlayerSliceStage(const std::string &color) cons if (totalPoints >= static_cast<int>(WheelStagePointsEnum_t::THREE)) { return WheelStageEnum_t::THREE; - } else if (totalPoints >= static_cast<int>(WheelStagePointsEnum_t::TWO)) { + } + if (totalPoints >= static_cast<int>(WheelStagePointsEnum_t::TWO)) { return WheelStageEnum_t::TWO; - } else if (totalPoints >= static_cast<uint8_t>(WheelStagePointsEnum_t::ONE)) { + } + if (totalPoints >= static_cast<uint8_t>(WheelStagePointsEnum_t::ONE)) { return WheelStageEnum_t::ONE; } @@ -2440,7 +2596,7 @@ void PlayerWheel::checkAbilities() { if (getInstant("Battle Instinct") && getOnThinkTimer(WheelOnThink_t::BATTLE_INSTINCT) < OTSYS_TIME() && checkBattleInstinct()) { reloadClient = true; } - if (getInstant("Positional Tatics") && getOnThinkTimer(WheelOnThink_t::POSITIONAL_TATICS) < OTSYS_TIME() && checkPositionalTatics()) { + if (getInstant("Positional Tactics") && getOnThinkTimer(WheelOnThink_t::POSITIONAL_TACTICS) < OTSYS_TIME() && checkPositionalTactics()) { reloadClient = true; } if (getInstant("Ballistic Mastery") && getOnThinkTimer(WheelOnThink_t::BALLISTIC_MASTERY) < OTSYS_TIME() && checkBallisticMastery()) { @@ -2457,40 +2613,12 @@ bool PlayerWheel::checkBattleInstinct() { setOnThinkTimer(WheelOnThink_t::BATTLE_INSTINCT, OTSYS_TIME() + 2000); bool updateClient = false; m_creaturesNearby = 0; - uint16_t creaturesNearby = 0; - for (int offsetX = -1; offsetX <= 1; offsetX++) { - if (creaturesNearby >= 8) { - break; - } - for (int offsetY = -1; offsetY <= 1; offsetY++) { - if (creaturesNearby >= 8) { - break; - } - - const auto playerPositionOffSet = Position( - m_player.getPosition().x + offsetX, - m_player.getPosition().y + offsetY, - m_player.getPosition().z - ); - std::shared_ptr<Tile> tile = g_game().map.getTile(playerPositionOffSet); - if (!tile) { - continue; - } - - std::shared_ptr<Creature> creature = tile->getTopVisibleCreature(m_player.getPlayer()); - if (!creature || creature == m_player.getPlayer() || (creature->getMaster() && creature->getMaster()->getPlayer() == m_player.getPlayer())) { - continue; - } - - creaturesNearby++; - } - } - + uint16_t creaturesNearby = Spectators().find<Monster>(m_player.getPosition(), false, 1, 1, 1, 1).excludePlayerMaster().size(); if (creaturesNearby >= 5) { m_creaturesNearby = creaturesNearby; creaturesNearby -= 4; - uint16_t meleeSkill = 1 * creaturesNearby; - uint16_t shieldSkill = 6 * creaturesNearby; + const uint16_t meleeSkill = 1 * creaturesNearby; + const uint16_t shieldSkill = 6 * creaturesNearby; if (getMajorStat(WheelMajor_t::MELEE) != meleeSkill || getMajorStat(WheelMajor_t::SHIELD) != shieldSkill) { setMajorStat(WheelMajor_t::MELEE, meleeSkill); setMajorStat(WheelMajor_t::SHIELD, shieldSkill); @@ -2505,45 +2633,26 @@ bool PlayerWheel::checkBattleInstinct() { return updateClient; } -bool PlayerWheel::checkPositionalTatics() { - setOnThinkTimer(WheelOnThink_t::POSITIONAL_TATICS, OTSYS_TIME() + 2000); +bool PlayerWheel::checkPositionalTactics() { + setOnThinkTimer(WheelOnThink_t::POSITIONAL_TACTICS, OTSYS_TIME() + 2000); m_creaturesNearby = 0; bool updateClient = false; - uint16_t creaturesNearby = 0; - for (int offsetX = -1; offsetX <= 1; offsetX++) { - if (creaturesNearby > 0) { - break; - } - for (int offsetY = -1; offsetY <= 1; offsetY++) { - const auto playerPositionOffSet = Position( - m_player.getPosition().x + offsetX, - m_player.getPosition().y + offsetY, - m_player.getPosition().z - ); - std::shared_ptr<Tile> tile = g_game().map.getTile(playerPositionOffSet); - if (!tile) { - continue; - } - - std::shared_ptr<Creature> creature = tile->getTopVisibleCreature(m_player.getPlayer()); - if (!creature || creature == m_player.getPlayer() || !creature->getMonster() || (creature->getMaster() && creature->getMaster()->getPlayer())) { - continue; - } - - creaturesNearby++; - break; - } - } - uint16_t magicSkill = 3; - uint16_t distanceSkill = 3; + uint16_t creaturesNearby = Spectators().find<Monster>(m_player.getPosition(), false, 1, 1, 1, 1).excludePlayerMaster().size(); + constexpr uint16_t holyMagicSkill = 3; + constexpr uint16_t healingMagicSkill = 3; + constexpr uint16_t distanceSkill = 3; if (creaturesNearby == 0) { m_creaturesNearby = creaturesNearby; if (getMajorStat(WheelMajor_t::DISTANCE) != distanceSkill) { setMajorStat(WheelMajor_t::DISTANCE, distanceSkill); updateClient = true; } - if (getMajorStat(WheelMajor_t::MAGIC) != 0) { - setMajorStat(WheelMajor_t::MAGIC, 0); + if (getSpecializedMagic(COMBAT_HOLYDAMAGE) != 0) { + setSpecializedMagic(COMBAT_HOLYDAMAGE, 0); + updateClient = true; + } + if (getSpecializedMagic(COMBAT_HEALING) != 0) { + setSpecializedMagic(COMBAT_HEALING, 0); updateClient = true; } } else { @@ -2551,8 +2660,12 @@ bool PlayerWheel::checkPositionalTatics() { setMajorStat(WheelMajor_t::DISTANCE, 0); updateClient = true; } - if (getMajorStat(WheelMajor_t::MAGIC) != magicSkill) { - setMajorStat(WheelMajor_t::MAGIC, magicSkill); + if (getSpecializedMagic(COMBAT_HOLYDAMAGE) != holyMagicSkill) { + setSpecializedMagic(COMBAT_HOLYDAMAGE, holyMagicSkill); + updateClient = true; + } + if (getSpecializedMagic(COMBAT_HEALING) != healingMagicSkill) { + setSpecializedMagic(COMBAT_HEALING, healingMagicSkill); updateClient = true; } } @@ -2563,11 +2676,11 @@ bool PlayerWheel::checkPositionalTatics() { bool PlayerWheel::checkBallisticMastery() { setOnThinkTimer(WheelOnThink_t::BALLISTIC_MASTERY, OTSYS_TIME() + 2000); bool updateClient = false; - int32_t newCritical = 1000; - uint16_t newHolyBonus = 2; // 2% - uint16_t newPhysicalBonus = 2; // 2% + constexpr int32_t newCritical = 1000; + constexpr uint16_t newHolyBonus = 2; // 2% + constexpr uint16_t newPhysicalBonus = 2; // 2% - std::shared_ptr<Item> item = m_player.getWeapon(); + const auto &item = m_player.getWeapon(); if (item && item->getAmmoType() == AMMO_BOLT) { if (getMajorStat(WheelMajor_t::CRITICAL_DMG) != newCritical) { setMajorStat(WheelMajor_t::CRITICAL_DMG, newCritical); @@ -2606,9 +2719,9 @@ bool PlayerWheel::checkBallisticMastery() { bool PlayerWheel::checkCombatMastery() { setOnThinkTimer(WheelOnThink_t::COMBAT_MASTERY, OTSYS_TIME() + 2000); bool updateClient = false; - uint8_t stage = getStage(WheelStage_t::COMBAT_MASTERY); + const uint8_t stage = getStage(WheelStage_t::COMBAT_MASTERY); - std::shared_ptr<Item> item = m_player.getWeapon(); + const auto &item = m_player.getWeapon(); if (item && item->getSlotPosition() & SLOTP_TWO_HAND) { int32_t criticalSkill = 0; if (stage >= 3) { @@ -2653,12 +2766,12 @@ bool PlayerWheel::checkDivineEmpowerment() { bool updateClient = false; setOnThinkTimer(WheelOnThink_t::DIVINE_EMPOWERMENT, OTSYS_TIME() + 1000); - const auto tile = m_player.getTile(); + const auto &tile = m_player.getTile(); if (!tile) { return updateClient; } - const auto items = tile->getItemList(); + const auto &items = tile->getItemList(); if (!items) { return updateClient; } @@ -2673,7 +2786,7 @@ bool PlayerWheel::checkDivineEmpowerment() { } if (isOwner) { - uint8_t stage = getStage(WheelStage_t::DIVINE_EMPOWERMENT); + const uint8_t stage = getStage(WheelStage_t::DIVINE_EMPOWERMENT); if (stage >= 3) { damageBonus = 7; } else if (stage >= 2) { @@ -2691,13 +2804,13 @@ bool PlayerWheel::checkDivineEmpowerment() { return updateClient; } -int32_t PlayerWheel::checkDivineGrenade(std::shared_ptr<Creature> target) const { +int32_t PlayerWheel::checkDivineGrenade(const std::shared_ptr<Creature> &target) const { if (!target || target == m_player.getPlayer()) { return 0; } int32_t damageBonus = 0; - uint8_t stage = getStage(WheelStage_t::DIVINE_GRENADE); + const uint8_t stage = getStage(WheelStage_t::DIVINE_GRENADE); if (stage >= 3) { damageBonus = 100; @@ -2719,7 +2832,7 @@ void PlayerWheel::checkGiftOfLife() { g_game().addMagicEffect(m_player.getPosition(), CONST_ME_WATER_DROP); g_game().combatChangeHealth(m_player.getPlayer(), m_player.getPlayer(), giftDamage); // Condition cooldown reduction - uint16_t reductionTimer = 60000; + constexpr uint16_t reductionTimer = 60000; reduceAllSpellsCooldownTimer(reductionTimer); // Set cooldown @@ -2727,14 +2840,14 @@ void PlayerWheel::checkGiftOfLife() { sendGiftOfLifeCooldown(); } -int32_t PlayerWheel::checkBlessingGroveHealingByTarget(std::shared_ptr<Creature> target) const { +int32_t PlayerWheel::checkBlessingGroveHealingByTarget(const std::shared_ptr<Creature> &target) const { if (!target || target == m_player.getPlayer()) { return 0; } int32_t healingBonus = 0; - uint8_t stage = getStage(WheelStage_t::BLESSING_OF_THE_GROVE); - int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); + const uint8_t stage = getStage(WheelStage_t::BLESSING_OF_THE_GROVE); + const int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); if (healthPercent <= 30) { if (stage >= 3) { healingBonus = 24; @@ -2756,14 +2869,14 @@ int32_t PlayerWheel::checkBlessingGroveHealingByTarget(std::shared_ptr<Creature> return healingBonus; } -int32_t PlayerWheel::checkTwinBurstByTarget(std::shared_ptr<Creature> target) const { +int32_t PlayerWheel::checkTwinBurstByTarget(const std::shared_ptr<Creature> &target) const { if (!target || target == m_player.getPlayer()) { return 0; } int32_t damageBonus = 0; - uint8_t stage = getStage(WheelStage_t::TWIN_BURST); - int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); + const uint8_t stage = getStage(WheelStage_t::TWIN_BURST); + const int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); if (healthPercent > 60) { if (stage >= 3) { damageBonus = 60; @@ -2777,14 +2890,14 @@ int32_t PlayerWheel::checkTwinBurstByTarget(std::shared_ptr<Creature> target) co return damageBonus; } -int32_t PlayerWheel::checkExecutionersThrow(std::shared_ptr<Creature> target) const { +int32_t PlayerWheel::checkExecutionersThrow(const std::shared_ptr<Creature> &target) const { if (!target || target == m_player.getPlayer()) { return 0; } int32_t damageBonus = 0; - uint8_t stage = getStage(WheelStage_t::EXECUTIONERS_THROW); - int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); + const uint8_t stage = getStage(WheelStage_t::EXECUTIONERS_THROW); + const int32_t healthPercent = std::round((static_cast<double>(target->getHealth()) * 100) / static_cast<double>(target->getMaxHealth())); if (healthPercent <= 30) { if (stage >= 3) { damageBonus = 150; @@ -2800,7 +2913,7 @@ int32_t PlayerWheel::checkExecutionersThrow(std::shared_ptr<Creature> target) co int32_t PlayerWheel::checkBeamMasteryDamage() const { int32_t damageBoost = 0; - uint8_t stage = getStage(WheelStage_t::BEAM_MASTERY); + const uint8_t stage = getStage(WheelStage_t::BEAM_MASTERY); if (stage >= 3) { damageBoost = 14; } else if (stage >= 2) { @@ -2812,12 +2925,12 @@ int32_t PlayerWheel::checkBeamMasteryDamage() const { return damageBoost; } -int32_t PlayerWheel::checkDrainBodyLeech(std::shared_ptr<Creature> target, skills_t skill) const { +int32_t PlayerWheel::checkDrainBodyLeech(const std::shared_ptr<Creature> &target, skills_t skill) const { if (!target || !target->getMonster() || target->getWheelOfDestinyDrainBodyDebuff() == 0) { return 0; } - uint8_t stage = target->getWheelOfDestinyDrainBodyDebuff(); + const uint8_t stage = target->getWheelOfDestinyDrainBodyDebuff(); if (target->getBuff(BUFF_DAMAGERECEIVED) > 100 && skill == SKILL_MANA_LEECH_AMOUNT) { int32_t manaLeechSkill = 0; if (stage >= 3) { @@ -2846,14 +2959,14 @@ int32_t PlayerWheel::checkDrainBodyLeech(std::shared_ptr<Creature> target, skill } int32_t PlayerWheel::checkBattleHealingAmount() const { - double amount = (double)m_player.getSkillLevel(SKILL_SHIELD) * 0.2; - uint8_t healthPercent = (m_player.getHealth() * 100) / m_player.getMaxHealth(); + double amount = static_cast<double>(m_player.getSkillLevel(SKILL_SHIELD)) * 0.2; + const uint8_t healthPercent = (m_player.getHealth() * 100) / m_player.getMaxHealth(); if (healthPercent <= 30) { amount *= 3; } else if (healthPercent <= 60) { amount *= 2; } - return (int32_t)amount; + return static_cast<int32_t>(amount); } int32_t PlayerWheel::checkAvatarSkill(WheelAvatarSkill_t skill) const { @@ -2881,9 +2994,11 @@ int32_t PlayerWheel::checkAvatarSkill(WheelAvatarSkill_t skill) const { if (skill == WheelAvatarSkill_t::DAMAGE_REDUCTION) { if (stage >= 3) { return 15; - } else if (stage >= 2) { + } + if (stage >= 2) { return 10; - } else if (stage >= 1) { + } + if (stage >= 1) { return 5; } } else if (skill == WheelAvatarSkill_t::CRITICAL_CHANCE) { @@ -2891,9 +3006,11 @@ int32_t PlayerWheel::checkAvatarSkill(WheelAvatarSkill_t skill) const { } else if (skill == WheelAvatarSkill_t::CRITICAL_DAMAGE) { if (stage >= 3) { return 1500; - } else if (stage >= 2) { + } + if (stage >= 2) { return 1000; - } else if (stage >= 1) { + } + if (stage >= 1) { return 500; } } @@ -2925,7 +3042,7 @@ void PlayerWheel::onThink(bool force /* = false*/) { if (getGiftOfCooldown() > 0 /*getInstant("Gift of Life")*/ && getOnThinkTimer(WheelOnThink_t::GIFT_OF_LIFE) <= OTSYS_TIME()) { decreaseGiftOfCooldown(1); } - if (!m_player.hasCondition(CONDITION_INFIGHT) || m_player.getZoneType() == ZONE_PROTECTION || (!getInstant("Battle Instinct") && !getInstant("Positional Tatics") && !getInstant("Ballistic Mastery") && !getInstant("Gift of Life") && !getInstant("Combat Mastery") && !getInstant("Divine Empowerment") && getGiftOfCooldown() == 0)) { + if (!m_player.hasCondition(CONDITION_INFIGHT) || m_player.getZoneType() == ZONE_PROTECTION || (!getInstant("Battle Instinct") && !getInstant("Positional Tactics") && !getInstant("Ballistic Mastery") && !getInstant("Gift of Life") && !getInstant("Combat Mastery") && !getInstant("Divine Empowerment") && getGiftOfCooldown() == 0)) { bool mustReset = false; for (int i = 0; i < static_cast<int>(WheelMajor_t::TOTAL_COUNT); i++) { if (getMajorStat(static_cast<WheelMajor_t>(i)) != 0) { @@ -2950,8 +3067,8 @@ void PlayerWheel::onThink(bool force /* = false*/) { if (getInstant("Battle Instinct") && (force || getOnThinkTimer(WheelOnThink_t::BATTLE_INSTINCT) < OTSYS_TIME()) && checkBattleInstinct()) { updateClient = true; } - // Positional Tatics - if (getInstant("Positional Tatics") && (force || getOnThinkTimer(WheelOnThink_t::POSITIONAL_TATICS) < OTSYS_TIME()) && checkPositionalTatics()) { + // Positional Tactics + if (getInstant("Positional Tactics") && (force || getOnThinkTimer(WheelOnThink_t::POSITIONAL_TACTICS) < OTSYS_TIME()) && checkPositionalTactics()) { updateClient = true; } // Ballistic Mastery @@ -2972,14 +3089,35 @@ void PlayerWheel::onThink(bool force /* = false*/) { } } -void PlayerWheel::reduceAllSpellsCooldownTimer(int32_t value) { +void PlayerWheel::reduceAllSpellsCooldownTimer(int32_t value) const { for (const auto &condition : m_player.getConditionsByType(CONDITION_SPELLCOOLDOWN)) { - if (condition->getTicks() <= value) { - m_player.sendSpellCooldown(condition->getSubId(), 0); - condition->endCondition(m_player.getPlayer()); - } else { - condition->setTicks(condition->getTicks() - value); - m_player.sendSpellCooldown(condition->getSubId(), condition->getTicks()); + const auto spellId = condition->getSubId(); + const auto &spell = g_spells().getInstantSpellById(spellId); + if (!spell) { + continue; + } + + const auto spellSecondaryGroup = spell->getSecondaryGroup(); + const auto &secondCondition = m_player.getCondition(CONDITION_SPELLGROUPCOOLDOWN, CONDITIONID_DEFAULT, spellSecondaryGroup); + + if (secondCondition) { + if (secondCondition->getTicks() <= value) { + m_player.sendSpellGroupCooldown(spellSecondaryGroup, 0); + secondCondition->endCondition(m_player.getPlayer()); + } else { + secondCondition->setTicks(secondCondition->getTicks() - value); + m_player.sendSpellGroupCooldown(spellSecondaryGroup, secondCondition->getTicks()); + } + } + + if (condition) { + if (condition->getTicks() <= value) { + m_player.sendSpellCooldown(spellId, 0); + condition->endCondition(m_player.getPlayer()); + } else { + condition->setTicks(condition->getTicks() - value); + m_player.sendSpellCooldown(spellId, condition->getTicks()); + } } } } @@ -2993,10 +3131,11 @@ void PlayerWheel::resetUpgradedSpells() { m_creaturesNearby = 0; m_spellsSelected.clear(); m_learnedSpellsSelected.clear(); + m_beamMasterySpells.clear(); for (int i = 0; i < static_cast<int>(WheelMajor_t::TOTAL_COUNT); i++) { setMajorStat(static_cast<WheelMajor_t>(i), 0); } - for (int i = 0; i < static_cast<int>(WheelStage_t::TOTAL_COUNT); i++) { + for (int i = 0; i < static_cast<int>(WheelStage_t::STAGE_COUNT); i++) { setStage(static_cast<WheelStage_t>(i), 0); } setOnThinkTimer(WheelOnThink_t::FOCUS_MASTERY, 0); @@ -3028,7 +3167,7 @@ void PlayerWheel::downgradeSpell(const std::string &name) { std::shared_ptr<Spell> PlayerWheel::getCombatDataSpell(CombatDamage &damage) { std::shared_ptr<Spell> spell = nullptr; - WheelSpellGrade_t spellGrade = WheelSpellGrade_t::NONE; + auto spellGrade = WheelSpellGrade_t::NONE; if (!(damage.instantSpellName).empty()) { spellGrade = getSpellUpgrade(damage.instantSpellName); spell = g_spells().getInstantSpellByName(damage.instantSpellName); @@ -3058,17 +3197,15 @@ std::shared_ptr<Spell> PlayerWheel::getCombatDataSpell(CombatDamage &damage) { damage.lifeLeechChance += spell->getWheelOfDestinyBoost(WheelSpellBoost_t::LIFE_LEECH_CHANCE, spellGrade); } - if (m_spellsBonuses.contains(spellName)) { - damage.criticalDamage += (getSpellBonus(spellName, WheelSpellBoost_t::CRITICAL_DAMAGE) * 100); - damage.criticalChance += getSpellBonus(spellName, WheelSpellBoost_t::CRITICAL_CHANCE); - damage.damageMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::DAMAGE); - damage.damageReductionMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::DAMAGE_REDUCTION); - damage.healingMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::HEAL); - damage.manaLeech += getSpellBonus(spellName, WheelSpellBoost_t::MANA_LEECH); - damage.manaLeechChance += getSpellBonus(spellName, WheelSpellBoost_t::MANA_LEECH_CHANCE); - damage.lifeLeech += getSpellBonus(spellName, WheelSpellBoost_t::LIFE_LEECH); - damage.lifeLeechChance += getSpellBonus(spellName, WheelSpellBoost_t::LIFE_LEECH_CHANCE); - } + damage.criticalDamage += (getSpellBonus(spellName, WheelSpellBoost_t::CRITICAL_DAMAGE) * 100); + damage.criticalChance += getSpellBonus(spellName, WheelSpellBoost_t::CRITICAL_CHANCE); + damage.damageMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::DAMAGE); + damage.damageReductionMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::DAMAGE_REDUCTION); + damage.healingMultiplier += getSpellBonus(spellName, WheelSpellBoost_t::HEAL); + damage.manaLeech += getSpellBonus(spellName, WheelSpellBoost_t::MANA_LEECH); + damage.manaLeechChance += getSpellBonus(spellName, WheelSpellBoost_t::MANA_LEECH_CHANCE); + damage.lifeLeech += getSpellBonus(spellName, WheelSpellBoost_t::LIFE_LEECH); + damage.lifeLeechChance += getSpellBonus(spellName, WheelSpellBoost_t::LIFE_LEECH_CHANCE); } return spell; @@ -3102,6 +3239,15 @@ void PlayerWheel::setMajorStat(WheelMajor_t type, int32_t value) { } } +void PlayerWheel::setSpecializedMagic(CombatType_t type, int32_t value) { + auto enumValue = static_cast<uint8_t>(type); + try { + m_specializedMagic.at(enumValue) = value; + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Type {} is out of range, value {}. Error message: {}", __FUNCTION__, enumValue, value, e.what()); + } +} + void PlayerWheel::setInstant(WheelInstant_t type, bool toggle) { auto enumValue = static_cast<uint8_t>(type); try { @@ -3138,9 +3284,9 @@ void PlayerWheel::setSpellInstant(const std::string &name, bool value) { } } else if (name == "Battle Healing") { setInstant(WheelInstant_t::BATTLE_HEALING, value); - } else if (name == "Positional Tatics") { - setInstant(WheelInstant_t::POSITIONAL_TATICS, value); - if (!getInstant(WheelInstant_t::POSITIONAL_TATICS)) { + } else if (name == "Positional Tactics") { + setInstant(WheelInstant_t::POSITIONAL_TACTICS, value); + if (!getInstant(WheelInstant_t::POSITIONAL_TACTICS)) { setMajorStat(WheelMajor_t::MAGIC, 0); setMajorStat(WheelMajor_t::HOLY_RESISTANCE, 0); } @@ -3264,47 +3410,41 @@ bool PlayerWheel::getInstant(WheelInstant_t type) const { return false; } -uint8_t PlayerWheel::getStage(const std::string name) const { - if (name == "Battle Instinct") { - return PlayerWheel::getInstant(WheelInstant_t::BATTLE_INSTINCT); - } else if (name == "Battle Healing") { - return PlayerWheel::getInstant(WheelInstant_t::BATTLE_HEALING); - } else if (name == "Positional Tatics") { - return PlayerWheel::getInstant(WheelInstant_t::POSITIONAL_TATICS); - } else if (name == "Ballistic Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::BALLISTIC_MASTERY); - } else if (name == "Healing Link") { - return PlayerWheel::getInstant(WheelInstant_t::HEALING_LINK); - } else if (name == "Runic Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::RUNIC_MASTERY); - } else if (name == "Focus Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::FOCUS_MASTERY); - } else if (name == "Beam Mastery") { - return PlayerWheel::getStage(WheelStage_t::BEAM_MASTERY); - } else if (name == "Combat Mastery") { - return PlayerWheel::getStage(WheelStage_t::COMBAT_MASTERY); - } else if (name == "Gift of Life") { - return PlayerWheel::getStage(WheelStage_t::GIFT_OF_LIFE); - } else if (name == "Blessing of the Grove") { - return PlayerWheel::getStage(WheelStage_t::BLESSING_OF_THE_GROVE); - } else if (name == "Drain Body") { - return PlayerWheel::getStage(WheelStage_t::DRAIN_BODY); - } else if (name == "Divine Empowerment") { - return PlayerWheel::getStage(WheelStage_t::DIVINE_EMPOWERMENT); - } else if (name == "Divine Grenade") { - return PlayerWheel::getStage(WheelStage_t::DIVINE_GRENADE); - } else if (name == "Twin Burst") { - return PlayerWheel::getStage(WheelStage_t::TWIN_BURST); - } else if (name == "Executioner's Throw") { - return PlayerWheel::getStage(WheelStage_t::EXECUTIONERS_THROW); - } else if (name == "Avatar of Light") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_LIGHT); - } else if (name == "Avatar of Nature") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_NATURE); - } else if (name == "Avatar of Steel") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_STEEL); - } else if (name == "Avatar of Storm") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_STORM); +uint8_t PlayerWheel::getStage(std::string_view name) const { + using enum WheelInstant_t; + using enum WheelStage_t; + + static const std::unordered_map<std::string_view, WheelInstant_t> instantMapping = { + { "Battle Instinct", BATTLE_INSTINCT }, + { "Battle Healing", BATTLE_HEALING }, + { "Positional Tatics", POSITIONAL_TACTICS }, + { "Ballistic Mastery", BALLISTIC_MASTERY }, + { "Healing Link", HEALING_LINK }, + { "Runic Mastery", RUNIC_MASTERY }, + { "Focus Mastery", FOCUS_MASTERY } + }; + + static const std::unordered_map<std::string_view, WheelStage_t> stageMapping = { + { "Beam Mastery", BEAM_MASTERY }, + { "Combat Mastery", COMBAT_MASTERY }, + { "Gift of Life", GIFT_OF_LIFE }, + { "Blessing of the Grove", BLESSING_OF_THE_GROVE }, + { "Drain Body", DRAIN_BODY }, + { "Divine Empowerment", DIVINE_EMPOWERMENT }, + { "Divine Grenade", DIVINE_GRENADE }, + { "Twin Burst", TWIN_BURST }, + { "Executioner's Throw", EXECUTIONERS_THROW }, + { "Avatar of Light", AVATAR_OF_LIGHT }, + { "Avatar of Nature", AVATAR_OF_NATURE }, + { "Avatar of Steel", AVATAR_OF_STEEL }, + { "Avatar of Storm", AVATAR_OF_STORM } + }; + + if (auto it = instantMapping.find(name); it != instantMapping.end()) { + return PlayerWheel::getInstant(it->second); + } + if (auto it = stageMapping.find(name); it != stageMapping.end()) { + return PlayerWheel::getStage(it->second); } return false; @@ -3330,6 +3470,16 @@ int32_t PlayerWheel::getMajorStat(WheelMajor_t type) const { return 0; } +int32_t PlayerWheel::getSpecializedMagic(CombatType_t type) const { + auto enumValue = static_cast<uint8_t>(type); + try { + return m_specializedMagic.at(enumValue); + } catch (const std::out_of_range &e) { + g_logger().error("[{}]. Instant type {}. Error message: {}", __FUNCTION__, enumValue, e.what()); + } + return 0; +} + int32_t PlayerWheel::getStat(WheelStat_t type) const { auto enumValue = static_cast<uint8_t>(type); try { @@ -3388,47 +3538,41 @@ int64_t PlayerWheel::getOnThinkTimer(WheelOnThink_t type) const { return 0; } -bool PlayerWheel::getInstant(const std::string name) const { - if (name == "Battle Instinct") { - return PlayerWheel::getInstant(WheelInstant_t::BATTLE_INSTINCT); - } else if (name == "Battle Healing") { - return PlayerWheel::getInstant(WheelInstant_t::BATTLE_HEALING); - } else if (name == "Positional Tatics") { - return PlayerWheel::getInstant(WheelInstant_t::POSITIONAL_TATICS); - } else if (name == "Ballistic Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::BALLISTIC_MASTERY); - } else if (name == "Healing Link") { - return PlayerWheel::getInstant(WheelInstant_t::HEALING_LINK); - } else if (name == "Runic Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::RUNIC_MASTERY); - } else if (name == "Focus Mastery") { - return PlayerWheel::getInstant(WheelInstant_t::FOCUS_MASTERY); - } else if (name == "Beam Mastery") { - return PlayerWheel::getStage(WheelStage_t::BEAM_MASTERY); - } else if (name == "Combat Mastery") { - return PlayerWheel::getStage(WheelStage_t::COMBAT_MASTERY); - } else if (name == "Gift of Life") { - return PlayerWheel::getStage(WheelStage_t::GIFT_OF_LIFE); - } else if (name == "Blessing of the Grove") { - return PlayerWheel::getStage(WheelStage_t::BLESSING_OF_THE_GROVE); - } else if (name == "Drain Body") { - return PlayerWheel::getStage(WheelStage_t::DRAIN_BODY); - } else if (name == "Divine Empowerment") { - return PlayerWheel::getStage(WheelStage_t::DIVINE_EMPOWERMENT); - } else if (name == "Divine Grenade") { - return PlayerWheel::getStage(WheelStage_t::DIVINE_GRENADE); - } else if (name == "Twin Burst") { - return PlayerWheel::getStage(WheelStage_t::TWIN_BURST); - } else if (name == "Executioner's Throw") { - return PlayerWheel::getStage(WheelStage_t::EXECUTIONERS_THROW); - } else if (name == "Avatar of Light") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_LIGHT); - } else if (name == "Avatar of Nature") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_NATURE); - } else if (name == "Avatar of Steel") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_STEEL); - } else if (name == "Avatar of Storm") { - return PlayerWheel::getStage(WheelStage_t::AVATAR_OF_STORM); +bool PlayerWheel::getInstant(std::string_view name) const { + using enum WheelInstant_t; + using enum WheelStage_t; + + static const std::unordered_map<std::string_view, WheelInstant_t> instantMapping = { + { "Battle Instinct", BATTLE_INSTINCT }, + { "Battle Healing", BATTLE_HEALING }, + { "Positional Tactics", POSITIONAL_TACTICS }, + { "Ballistic Mastery", BALLISTIC_MASTERY }, + { "Healing Link", HEALING_LINK }, + { "Runic Mastery", RUNIC_MASTERY }, + { "Focus Mastery", FOCUS_MASTERY } + }; + + static const std::unordered_map<std::string_view, WheelStage_t> stageMapping = { + { "Beam Mastery", BEAM_MASTERY }, + { "Combat Mastery", COMBAT_MASTERY }, + { "Gift of Life", GIFT_OF_LIFE }, + { "Blessing of the Grove", BLESSING_OF_THE_GROVE }, + { "Drain Body", DRAIN_BODY }, + { "Divine Empowerment", DIVINE_EMPOWERMENT }, + { "Divine Grenade", DIVINE_GRENADE }, + { "Twin Burst", TWIN_BURST }, + { "Executioner's Throw", EXECUTIONERS_THROW }, + { "Avatar of Light", AVATAR_OF_LIGHT }, + { "Avatar of Nature", AVATAR_OF_NATURE }, + { "Avatar of Steel", AVATAR_OF_STEEL }, + { "Avatar of Storm", AVATAR_OF_STORM } + }; + + if (auto it = instantMapping.find(name); it != instantMapping.end()) { + return PlayerWheel::getInstant(it->second); + } + if (auto it = stageMapping.find(name); it != stageMapping.end()) { + return PlayerWheel::getStage(it->second); } return false; @@ -3438,9 +3582,11 @@ bool PlayerWheel::getInstant(const std::string name) const { uint32_t PlayerWheel::getGiftOfLifeTotalCooldown() const { if (getStage(WheelStage_t::GIFT_OF_LIFE) == 1) { return 1 * 60 * 60 * 30; - } else if (getStage(WheelStage_t::GIFT_OF_LIFE) == 2) { + } + if (getStage(WheelStage_t::GIFT_OF_LIFE) == 2) { return 1 * 60 * 60 * 20; - } else if (getStage(WheelStage_t::GIFT_OF_LIFE) == 3) { + } + if (getStage(WheelStage_t::GIFT_OF_LIFE) == 3) { return 1 * 60 * 60 * 10; } return 0; @@ -3449,9 +3595,11 @@ uint32_t PlayerWheel::getGiftOfLifeTotalCooldown() const { uint8_t PlayerWheel::getGiftOfLifeValue() const { if (getStage(WheelStage_t::GIFT_OF_LIFE) == 1) { return 20; - } else if (getStage(WheelStage_t::GIFT_OF_LIFE) == 2) { + } + if (getStage(WheelStage_t::GIFT_OF_LIFE) == 2) { return 25; - } else if (getStage(WheelStage_t::GIFT_OF_LIFE) == 3) { + } + if (getStage(WheelStage_t::GIFT_OF_LIFE) == 3) { return 30; } @@ -3459,7 +3607,7 @@ uint8_t PlayerWheel::getGiftOfLifeValue() const { } int32_t PlayerWheel::getGiftOfCooldown() const { - int32_t value = m_player.getStorageValue(STORAGEVALUE_GIFT_OF_LIFE_COOLDOWN_WOD); + const int32_t value = m_player.getStorageValue(STORAGEVALUE_GIFT_OF_LIFE_COOLDOWN_WOD); if (value <= 0) { return 0; } @@ -3474,7 +3622,7 @@ void PlayerWheel::setGiftOfCooldown(int32_t value, bool isOnThink) { } void PlayerWheel::decreaseGiftOfCooldown(int32_t value) { - int32_t cooldown = getGiftOfCooldown() - value; + const int32_t cooldown = getGiftOfCooldown() - value; if (cooldown <= 0) { setOnThinkTimer(WheelOnThink_t::GIFT_OF_LIFE, OTSYS_TIME() + 3600000); return; @@ -3525,7 +3673,7 @@ void PlayerWheel::setWheelBonusData(const PlayerWheelMethodsBonusData &newBonusD // Functions used to Manage Combat uint8_t PlayerWheel::getBeamAffectedTotal(const CombatDamage &tmpDamage) const { uint8_t beamAffectedTotal = 0; // Removed const - if (tmpDamage.runeSpellName == "Beam Mastery" && getInstant("Beam Mastery")) { + if (m_beamMasterySpells.contains(tmpDamage.instantSpellName) && getInstant("Beam Mastery")) { beamAffectedTotal = 3; } return beamAffectedTotal; @@ -3534,6 +3682,7 @@ uint8_t PlayerWheel::getBeamAffectedTotal(const CombatDamage &tmpDamage) const { void PlayerWheel::updateBeamMasteryDamage(CombatDamage &tmpDamage, uint8_t &beamAffectedTotal, uint8_t &beamAffectedCurrent) const { if (beamAffectedTotal > 0) { tmpDamage.damageMultiplier += checkBeamMasteryDamage(); + reduceAllSpellsCooldownTimer(1000); // Reduces all spell cooldown by 1 second per target hit (max 3 seconds) --beamAffectedTotal; beamAffectedCurrent++; } @@ -3549,7 +3698,7 @@ void PlayerWheel::healIfBattleHealingActive() const { } void PlayerWheel::adjustDamageBasedOnResistanceAndSkill(int32_t &damage, CombatType_t combatType) const { - int32_t wheelOfDestinyElementAbsorb = getResistance(combatType); + const int32_t wheelOfDestinyElementAbsorb = getResistance(combatType); if (wheelOfDestinyElementAbsorb > 0) { damage -= std::ceil((damage * wheelOfDestinyElementAbsorb) / 10000.); } @@ -3558,11 +3707,8 @@ void PlayerWheel::adjustDamageBasedOnResistanceAndSkill(int32_t &damage, CombatT } float PlayerWheel::calculateMitigation() const { - int32_t skill = m_player.getSkillLevel(SKILL_SHIELD); + const int32_t skill = m_player.getSkillLevel(SKILL_SHIELD); int32_t defenseValue = 0; - std::shared_ptr<Item> weapon = m_player.inventory[CONST_SLOT_LEFT]; - std::shared_ptr<Item> shield = m_player.inventory[CONST_SLOT_RIGHT]; - float fightFactor = 1.0f; float shieldFactor = 1.0f; float distanceFactor = 1.0f; @@ -3583,6 +3729,7 @@ float PlayerWheel::calculateMitigation() const { break; } + const auto &shield = m_player.inventory[CONST_SLOT_RIGHT]; if (shield) { if (shield->isSpellBook() || shield->isQuiver()) { distanceFactor = m_player.vocation->mitigationSecondaryShield; @@ -3596,6 +3743,7 @@ float PlayerWheel::calculateMitigation() const { } } + const auto &weapon = m_player.inventory[CONST_SLOT_LEFT]; if (weapon) { if (weapon->getAmmoType() == AMMO_BOLT || weapon->getAmmoType() == AMMO_ARROW) { distanceFactor = m_player.vocation->mitigationSecondaryShield; @@ -3608,8 +3756,8 @@ float PlayerWheel::calculateMitigation() const { } } - float mitigation = std::ceil(((((skill * m_player.vocation->mitigationFactor) + (shieldFactor * (float)defenseValue)) / 100.0f) * fightFactor * distanceFactor) * 100.0f) / 100.0f; - mitigation += (mitigation * (float)getMitigationMultiplier()) / 100.f; + float mitigation = std::ceil(((((skill * m_player.vocation->mitigationFactor) + (shieldFactor * static_cast<float>(defenseValue))) / 100.0f) * fightFactor * distanceFactor) * 100.0f) / 100.0f; + mitigation += (mitigation * static_cast<float>(getMitigationMultiplier())) / 100.f; return mitigation; } diff --git a/src/creatures/players/wheel/player_wheel.hpp b/src/creatures/players/wheel/player_wheel.hpp index a99b3dac49a..7c3bd2348a6 100644 --- a/src/creatures/players/wheel/player_wheel.hpp +++ b/src/creatures/players/wheel/player_wheel.hpp @@ -9,6 +9,7 @@ #pragma once +#include "creatures/creatures_definitions.hpp" #include "creatures/players/wheel/wheel_definitions.hpp" class Creature; @@ -20,11 +21,16 @@ class Spell; class WheelModifierContext; class ValueWrapper; +struct CombatDamage; + enum class WheelFragmentType_t : uint8_t; enum class WheelGemAffinity_t : uint8_t; enum class WheelGemBasicModifier_t : uint8_t; enum class WheelGemQuality_t : uint8_t; enum class WheelGemSupremeModifier_t : uint8_t; +enum CombatType_t : uint8_t; +enum skills_t : int8_t; +enum Vocation_t : uint16_t; struct PlayerWheelGem { std::string uuid; @@ -101,6 +107,9 @@ class PlayerWheel { int getSpellAdditionalDuration(const std::string &spellName) const; bool getSpellAdditionalArea(const std::string &spellName) const; + bool handleTwinBurstsCooldown(const std::shared_ptr<Player> &player, const std::string &spellName, int spellCooldown, int rateCooldown) const; + bool handleBeamMasteryCooldown(const std::shared_ptr<Player> &player, const std::string &spellName, int spellCooldown, int rateCooldown) const; + /* * Functions for manage slots */ @@ -128,7 +137,7 @@ class PlayerWheel { void setPlayerCombatStats(CombatType_t type, int32_t leechAmount); - void reloadPlayerData(); + void reloadPlayerData() const; void registerPlayerBonusData(); @@ -203,22 +212,22 @@ class PlayerWheel { void checkAbilities(); void checkGiftOfLife(); bool checkBattleInstinct(); - bool checkPositionalTatics(); + bool checkPositionalTactics(); bool checkBallisticMastery(); bool checkCombatMastery(); bool checkDivineEmpowerment(); - int32_t checkDrainBodyLeech(std::shared_ptr<Creature> target, skills_t skill) const; + int32_t checkDrainBodyLeech(const std::shared_ptr<Creature> &target, skills_t skill) const; int32_t checkBeamMasteryDamage() const; int32_t checkBattleHealingAmount() const; - int32_t checkBlessingGroveHealingByTarget(std::shared_ptr<Creature> target) const; - int32_t checkTwinBurstByTarget(std::shared_ptr<Creature> target) const; - int32_t checkExecutionersThrow(std::shared_ptr<Creature> target) const; - int32_t checkDivineGrenade(std::shared_ptr<Creature> target) const; + int32_t checkBlessingGroveHealingByTarget(const std::shared_ptr<Creature> &target) const; + int32_t checkTwinBurstByTarget(const std::shared_ptr<Creature> &target) const; + int32_t checkExecutionersThrow(const std::shared_ptr<Creature> &target) const; + int32_t checkDivineGrenade(const std::shared_ptr<Creature> &target) const; int32_t checkAvatarSkill(WheelAvatarSkill_t skill) const; int32_t checkFocusMasteryDamage(); int32_t checkElementSensitiveReduction(CombatType_t type) const; // Wheel of destiny - General functions: - void reduceAllSpellsCooldownTimer(int32_t value); + void reduceAllSpellsCooldownTimer(int32_t value) const; void resetUpgradedSpells(); void upgradeSpell(const std::string &name); void downgradeSpell(const std::string &name); @@ -254,6 +263,16 @@ class PlayerWheel { */ void setMajorStat(WheelMajor_t type, int32_t value); + /** + * @brief Sets the value of a specific specialized magic in the Wheel of Destiny. + * + * This function sets the value of the specified specialized magic in the Wheel of Destiny to the provided value. + * + * @param type The type of the combat to set the specialized magic. + * @param value The value to set for the specialized magic. + */ + void setSpecializedMagic(CombatType_t type, int32_t value); + /** * @brief Sets the value of a specific instant in the Wheel of Destiny. * @@ -300,15 +319,16 @@ class PlayerWheel { // Wheel of destiny - Header get: bool getInstant(WheelInstant_t type) const; bool getHealingLinkUpgrade(const std::string &spell) const; - uint8_t getStage(const std::string name) const; + uint8_t getStage(std::string_view name) const; uint8_t getStage(WheelStage_t type) const; WheelSpellGrade_t getSpellUpgrade(const std::string &name) const; int32_t getMajorStat(WheelMajor_t type) const; + int32_t getSpecializedMagic(CombatType_t type) const; int32_t getStat(WheelStat_t type) const; int32_t getResistance(CombatType_t type) const; int32_t getMajorStatConditional(const std::string &instant, WheelMajor_t major) const; int64_t getOnThinkTimer(WheelOnThink_t type) const; - bool getInstant(const std::string name) const; + bool getInstant(std::string_view name) const; double getMitigationMultiplier() const; // Wheel of destiny - Specific functions @@ -367,69 +387,17 @@ class PlayerWheel { PlayerWheelGem getGem(uint16_t index) const; PlayerWheelGem getGem(const std::string &uuid) const; uint16_t getGemIndex(const std::string &uuid) const; - void revealGem(WheelGemQuality_t quality); - void destroyGem(uint16_t index); - void switchGemDomain(uint16_t index); - void toggleGemLock(uint16_t index); - void setActiveGem(WheelGemAffinity_t affinity, uint16_t index); - void removeActiveGem(WheelGemAffinity_t affinity); - void addRevelationBonus(WheelGemAffinity_t affinity, uint16_t points) { - m_bonusRevelationPoints[static_cast<size_t>(affinity)] += points; - } - void resetRevelationBonus() { - m_bonusRevelationPoints = { 0, 0, 0, 0 }; - } - - void addSpellBonus(const std::string &spellName, WheelSpells::Bonus bonus) { - if (m_spellsBonuses.contains(spellName)) { - m_spellsBonuses[spellName].decrease.cooldown += bonus.decrease.cooldown; - m_spellsBonuses[spellName].decrease.manaCost += bonus.decrease.manaCost; - m_spellsBonuses[spellName].decrease.secondaryGroupCooldown += bonus.decrease.secondaryGroupCooldown; - m_spellsBonuses[spellName].increase.aditionalTarget += bonus.increase.aditionalTarget; - m_spellsBonuses[spellName].increase.area = bonus.increase.area; - m_spellsBonuses[spellName].increase.criticalChance += bonus.increase.criticalChance; - m_spellsBonuses[spellName].increase.criticalDamage += bonus.increase.criticalDamage; - m_spellsBonuses[spellName].increase.damage += bonus.increase.damage; - m_spellsBonuses[spellName].increase.damageReduction += bonus.increase.damageReduction; - m_spellsBonuses[spellName].increase.duration += bonus.increase.duration; - m_spellsBonuses[spellName].increase.heal += bonus.increase.heal; - m_spellsBonuses[spellName].leech.life += bonus.leech.life; - m_spellsBonuses[spellName].leech.mana += bonus.leech.mana; - return; - } - m_spellsBonuses[spellName] = bonus; - } - - int32_t getSpellBonus(const std::string &spellName, WheelSpellBoost_t boost) const { - if (!m_spellsBonuses.contains(spellName)) { - return 0; - } - auto bonus = m_spellsBonuses.at(spellName); - switch (boost) { - case WheelSpellBoost_t::COOLDOWN: - return bonus.decrease.cooldown; - case WheelSpellBoost_t::MANA: - return bonus.decrease.manaCost; - case WheelSpellBoost_t::SECONDARY_GROUP_COOLDOWN: - return bonus.decrease.secondaryGroupCooldown; - case WheelSpellBoost_t::CRITICAL_CHANCE: - return bonus.increase.criticalChance; - case WheelSpellBoost_t::CRITICAL_DAMAGE: - return bonus.increase.criticalDamage; - case WheelSpellBoost_t::DAMAGE: - return bonus.increase.damage; - case WheelSpellBoost_t::DAMAGE_REDUCTION: - return bonus.increase.damageReduction; - case WheelSpellBoost_t::HEAL: - return bonus.increase.heal; - case WheelSpellBoost_t::LIFE_LEECH: - return bonus.leech.life; - case WheelSpellBoost_t::MANA_LEECH: - return bonus.leech.mana; - default: - return 0; - } - } + void revealGem(WheelGemQuality_t quality) const; + void destroyGem(uint16_t index) const; + void switchGemDomain(uint16_t index) const; + void toggleGemLock(uint16_t index) const; + void setActiveGem(WheelGemAffinity_t affinity, uint16_t index) const; + void removeActiveGem(WheelGemAffinity_t affinity) const; + void addRevelationBonus(WheelGemAffinity_t affinity, uint16_t points); + void resetRevelationBonus(); + void addSpellBonus(const std::string &spellName, const WheelSpells::Bonus &bonus); + + int32_t getSpellBonus(const std::string &spellName, WheelSpellBoost_t boost) const; WheelGemBasicModifier_t selectBasicModifier2(WheelGemBasicModifier_t modifier1) const; @@ -453,15 +421,17 @@ class PlayerWheel { PlayerWheelMethodsBonusData m_playerBonusData; std::unique_ptr<WheelModifierContext> m_modifierContext; - std::array<uint8_t, static_cast<size_t>(WheelStage_t::TOTAL_COUNT)> m_stages = { 0 }; + std::array<uint8_t, static_cast<size_t>(WheelStage_t::STAGE_COUNT)> m_stages = { 0 }; std::array<int64_t, static_cast<size_t>(WheelOnThink_t::TOTAL_COUNT)> m_onThink = { 0 }; std::array<int32_t, static_cast<size_t>(WheelStat_t::TOTAL_COUNT)> m_stats = { 0 }; std::array<int32_t, static_cast<size_t>(WheelMajor_t::TOTAL_COUNT)> m_majorStats = { 0 }; - std::array<bool, static_cast<size_t>(WheelInstant_t::TOTAL_COUNT)> m_instant = { false }; + std::array<bool, static_cast<size_t>(WheelInstant_t::INSTANT_COUNT)> m_instant = { false }; std::array<int32_t, COMBAT_COUNT> m_resistance = { 0 }; + std::array<int32_t, COMBAT_COUNT> m_specializedMagic = { 0 }; int32_t m_creaturesNearby = 0; std::map<std::string, WheelSpellGrade_t> m_spellsSelected; std::vector<std::string> m_learnedSpellsSelected; std::unordered_map<std::string, WheelSpells::Bonus> m_spellsBonuses; + std::unordered_set<std::string> m_beamMasterySpells; }; diff --git a/src/creatures/players/wheel/wheel_definitions.hpp b/src/creatures/players/wheel/wheel_definitions.hpp index 8fc3783b4cb..a136bd620d3 100644 --- a/src/creatures/players/wheel/wheel_definitions.hpp +++ b/src/creatures/players/wheel/wheel_definitions.hpp @@ -9,8 +9,6 @@ #pragma once -#include "creatures/creatures_definitions.hpp" - enum WheelSlots_t : uint8_t { SLOT_GREEN_200 = 1, SLOT_GREEN_TOP_150 = 2, @@ -94,12 +92,12 @@ enum class WheelStage_t : uint8_t { AVATAR_OF_STORM = 11, DIVINE_GRENADE = 12, - TOTAL_COUNT = 13 + STAGE_COUNT = 13 }; enum class WheelOnThink_t : uint8_t { BATTLE_INSTINCT = 0, - POSITIONAL_TATICS = 1, + POSITIONAL_TACTICS = 1, BALLISTIC_MASTERY = 2, COMBAT_MASTERY = 3, FOCUS_MASTERY = 4, @@ -150,13 +148,13 @@ enum class WheelMajor_t : uint8_t { enum class WheelInstant_t : uint8_t { BATTLE_INSTINCT = 0, BATTLE_HEALING = 1, - POSITIONAL_TATICS = 2, + POSITIONAL_TACTICS = 2, BALLISTIC_MASTERY = 3, HEALING_LINK = 4, RUNIC_MASTERY = 5, FOCUS_MASTERY = 6, - TOTAL_COUNT = 7 + INSTANT_COUNT = 7 }; enum class WheelAvatarSkill_t : uint8_t { @@ -219,7 +217,7 @@ struct PlayerWheelMethodsBonusData { struct Instant { bool battleInstinct = false; // Knight bool battleHealing = false; // Knight - bool positionalTatics = false; // Paladin + bool positionalTactics = false; // Paladin bool ballisticMastery = false; // Paladin bool healingLink = false; // Druid bool runicMastery = false; // Druid/sorcerer @@ -284,7 +282,7 @@ namespace WheelSpells { struct Decrease { int cooldown = 0; int manaCost = 0; - uint8_t secondaryGroupCooldown = 0; + int secondaryGroupCooldown = 0; }; struct Leech { diff --git a/src/creatures/players/wheel/wheel_gems.cpp b/src/creatures/players/wheel/wheel_gems.cpp index fb77643913a..766fa9ee049 100644 --- a/src/creatures/players/wheel/wheel_gems.cpp +++ b/src/creatures/players/wheel/wheel_gems.cpp @@ -9,6 +9,7 @@ #include "creatures/players/wheel/wheel_gems.hpp" +#include "creatures/creatures_definitions.hpp" #include "creatures/players/wheel/player_wheel.hpp" #include "enums/player_wheel.hpp" @@ -40,181 +41,181 @@ void WheelModifierContext::addStrategies(WheelGemBasicModifier_t modifier, uint8 switch (modifier) { case WheelGemBasicModifier_t::General_PhysicalResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_PHYSICALDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_PHYSICALDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_HolyResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_DeathResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_FireResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 200 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 200 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_EarthResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 200 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 200 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_IceResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 200 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 200 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 200 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 200 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_HolyResistance_DeathWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, 150 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, -100)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, -100)); break; case WheelGemBasicModifier_t::General_DeathResistance_HolyWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, 150 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, -100)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_DEATHDAMAGE, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_HOLYDAMAGE, -100)); break; case WheelGemBasicModifier_t::General_FireResistance_EarthResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_FireResistance_IceResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_FireResistance_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_EarthResistance_IceResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_EarthResistance_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_IceResistance_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_FireResistance_EarthWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_FireResistance_IceWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_FireResistance_EnergyWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EarthResistance_FireWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EarthResistance_IceWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EarthResistance_EnergyWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_IceResistance_EarthWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_IceResistance_FireWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_IceResistance_EnergyWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EnergyResistance_EarthWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EnergyResistance_IceWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_EnergyResistance_FireWeakness: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, -200)); break; case WheelGemBasicModifier_t::General_ManaDrainResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_MANADRAIN, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_MANADRAIN, 300 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_LifeDrainResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_LIFEDRAIN, 300 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_LIFEDRAIN, 300 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_ManaDrainResistance_LifeDrainResistance: - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_MANADRAIN, 150 * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_LIFEDRAIN, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_MANADRAIN, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_LIFEDRAIN, 150 * gradeMultiplier)); break; case WheelGemBasicModifier_t::General_MitigationMultiplier: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MITIGATION, 500 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MITIGATION, 500 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Health: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mana_FireResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mana_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mana_Earth_Resistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mana_Ice_Resistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mana: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Health_FireResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Health_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Health_EarthResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Health_IceResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Mixed: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::HEALTH, WheelGemUtils::getHealthValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA, WheelGemUtils::getManaValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Capacity_FireResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_FIREDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Capacity_EnergyResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ENERGYDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Capacity_EarthResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_EARTHDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Capacity_IceResistance: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); - m_strategies.push_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierResistanceStrategy>(m_wheel, CombatType_t::COMBAT_ICEDAMAGE, 100 * gradeMultiplier)); break; case WheelGemBasicModifier_t::Vocation_Capacity: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CAPACITY, WheelGemUtils::getCapacityValue(m_vocation, modifier) * gradeMultiplier)); break; default: @@ -237,331 +238,331 @@ void WheelModifierContext::addStrategies(WheelGemSupremeModifier_t modifier, uin switch (modifier) { case WheelGemSupremeModifier_t::General_Dodge: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::DODGE, 25 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::DODGE, 28 * gradeMultiplier)); break; case WheelGemSupremeModifier_t::General_LifeLeech: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::LIFE_LEECH, 120 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::LIFE_LEECH, 200 * gradeMultiplier)); break; case WheelGemSupremeModifier_t::General_ManaLeech: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA_LEECH, 40 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::MANA_LEECH, 80 * gradeMultiplier)); break; case WheelGemSupremeModifier_t::General_CriticalDamage: - m_strategies.push_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CRITICAL_DAMAGE, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierStatStrategy>(m_wheel, WheelStat_t::CRITICAL_DAMAGE, 200 * gradeMultiplier)); break; case WheelGemSupremeModifier_t::General_RevelationMastery_GiftOfLife: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Green, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Green, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Green, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::SorcererDruid_UltimateHealing: - bonus.increase.heal = 10 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ultimate Healing", bonus)); + bonus.increase.heal = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ultimate Healing", bonus)); break; case WheelGemSupremeModifier_t::Knight_RevelationMastery_ExecutionersThrow: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Red, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Knight_RevelationMastery_AvatarOfSteel: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Purple, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Knight_RevelationMastery_CombatMastery: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Blue, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Paladin_RevelationMastery_DivineGrenade: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Red, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Paladin_RevelationMastery_AvatarOfLight: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Purple, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Paladin_RevelationMastery_DivineEmpowerment: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Blue, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Druid_RevelationMastery_BlessingOfTheGrove: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Red, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Druid_RevelationMastery_AvatarOfNature: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Purple, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Druid_RevelationMastery_TwinBursts: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Blue, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Sorcerer_RevelationMastery_BeamMastery: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Red, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Red, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Sorcerer_RevelationMastery_AvatarOfStorm: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Purple, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Purple, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Sorcerer_RevelationMastery_DrainBody: - m_strategies.push_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierRevelationStrategy>(m_wheel, WheelGemAffinity_t::Blue, 150 * gradeMultiplier)); m_wheel.addRevelationBonus(WheelGemAffinity_t::Blue, 150 * gradeMultiplier); break; case WheelGemSupremeModifier_t::Knight_AvatarOfSteel_Cooldown: - bonus.decrease.cooldown = 300 * 1000; + bonus.decrease.cooldown = 900 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Steel", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Steel", bonus)); break; case WheelGemSupremeModifier_t::Knight_ExecutionersThrow_Cooldown: - bonus.decrease.cooldown = 1 * 1000; + bonus.decrease.cooldown = 2 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); break; case WheelGemSupremeModifier_t::Knight_ExecutionersThrow_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); + bonus.increase.damage = 6 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); break; case WheelGemSupremeModifier_t::Knight_ExecutionersThrow_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Executioner's Throw", bonus)); break; case WheelGemSupremeModifier_t::Knight_Fierce_Berserk_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fierce Berserk", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fierce Berserk", bonus)); break; case WheelGemSupremeModifier_t::Knight_Fierce_Berserk_CriticalExtraDamage: bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fierce Berserk", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fierce Berserk", bonus)); break; case WheelGemSupremeModifier_t::Knight_Berserk_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Berserk", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Berserk", bonus)); break; case WheelGemSupremeModifier_t::Knight_Berserk_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Berserk", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Berserk", bonus)); break; case WheelGemSupremeModifier_t::Knight_Front_Sweep_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Front Sweep", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Front Sweep", bonus)); break; case WheelGemSupremeModifier_t::Knight_Front_Sweep_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Front Sweep", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Front Sweep", bonus)); break; case WheelGemSupremeModifier_t::Knight_Groundshaker_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Groundshaker", bonus)); + bonus.increase.damage = static_cast<int>(std::round(6.5 * gradeMultiplier)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Groundshaker", bonus)); break; case WheelGemSupremeModifier_t::Knight_Groundshaker_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Groundshaker", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Groundshaker", bonus)); break; case WheelGemSupremeModifier_t::Knight_Annihilation_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Annihilation", bonus)); + bonus.increase.criticalDamage = 15 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Annihilation", bonus)); break; case WheelGemSupremeModifier_t::Knight_Annihilation_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Annihilation", bonus)); + bonus.increase.damage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Annihilation", bonus)); break; case WheelGemSupremeModifier_t::Knight_FairWoundCleansing_HealingIncrease: bonus.increase.heal = 10 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fair Wound Cleansing", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Fair Wound Cleansing", bonus)); break; case WheelGemSupremeModifier_t::Paladin_AvatarOfLight_Cooldown: - bonus.decrease.cooldown = 300 * 1000; + bonus.decrease.cooldown = 900 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Light", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Light", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineDazzle_Cooldown: - bonus.decrease.cooldown = 2 * 1000; + bonus.decrease.cooldown = 4 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Dazzle", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Dazzle", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineGrenade_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); + bonus.increase.damage = 6 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineGrenade_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineCaldera_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Caldera", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Caldera", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineCaldera_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Caldera", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Caldera", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineMissile_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Missile", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Missile", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineMissile_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Missile", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Missile", bonus)); break; case WheelGemSupremeModifier_t::Paladin_EtherealSpear_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ethereal Spear", bonus)); + bonus.increase.damage = 10 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ethereal Spear", bonus)); break; case WheelGemSupremeModifier_t::Paladin_EtherealSpear_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ethereal Spear", bonus)); + bonus.increase.criticalDamage = 15 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ethereal Spear", bonus)); break; case WheelGemSupremeModifier_t::Paladin_StrongEtherealSpear_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ethereal Spear", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ethereal Spear", bonus)); break; case WheelGemSupremeModifier_t::Paladin_StrongEtherealSpear_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ethereal Spear", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ethereal Spear", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineEmpowerment_Cooldown: - bonus.decrease.cooldown = 3 * 1000; + bonus.decrease.cooldown = 6 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Empowerment", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Empowerment", bonus)); break; case WheelGemSupremeModifier_t::Paladin_DivineGrenade_Cooldown: - bonus.decrease.cooldown = 1 * 1000; + bonus.decrease.cooldown = 2 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Divine Grenade", bonus)); break; case WheelGemSupremeModifier_t::Paladin_Salvation_HealingIncrease: - bonus.increase.heal = 10 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Salvation", bonus)); + bonus.increase.heal = 6 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Salvation", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_AvatarOfStorm_Cooldown: - bonus.decrease.cooldown = 300 * 1000; + bonus.decrease.cooldown = 900 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Storm", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Storm", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_EnergyWave_Cooldown: bonus.decrease.cooldown = 1 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatDeathBeam_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Death Beam", bonus)); + bonus.increase.damage = 10 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Death Beam", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatDeathBeam_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Death Beam", bonus)); + bonus.increase.criticalDamage = 15 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Death Beam", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_HellsCore_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Hell's Core", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Hell's Core", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_HellsCore_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Hell's Core", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Hell's Core", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_EnergyWave_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_EnergyWave_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Energy Wave", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatFireWave_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Fire Wave", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Fire Wave", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatFireWave_CriticalExtraDamage: bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Fire Wave", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Fire Wave", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_RageOfTheSkies_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Rage of the Skies", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Rage of the Skies", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_RageOfTheSkies_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Rage of the Skies", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Rage of the Skies", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatEnergyBeam_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Energy Beam", bonus)); + bonus.increase.damage = 10 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Energy Beam", bonus)); break; case WheelGemSupremeModifier_t::Sorcerer_GreatEnergyBeam_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Energy Beam", bonus)); + bonus.increase.criticalDamage = 15 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Great Energy Beam", bonus)); break; case WheelGemSupremeModifier_t::Druid_AvatarOfNature_Cooldown: - bonus.decrease.cooldown = 300 * 1000; + bonus.decrease.cooldown = 900 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Nature", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Avatar of Nature", bonus)); break; case WheelGemSupremeModifier_t::Druid_NaturesEmbrace_Cooldown: bonus.decrease.cooldown = 5 * 1000; wheelBonus.momentum += grade < 3 ? 0.33 * grade : 1; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Nature's Embrace", bonus)); + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Nature's Embrace", bonus)); break; case WheelGemSupremeModifier_t::Druid_TerraBurst_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Burst", bonus)); + bonus.increase.damage = 7 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Burst", bonus)); break; case WheelGemSupremeModifier_t::Druid_TerraBurst_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Burst", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Burst", bonus)); break; case WheelGemSupremeModifier_t::Druid_IceBurst_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ice Burst", bonus)); + bonus.increase.damage = 7 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ice Burst", bonus)); break; case WheelGemSupremeModifier_t::Druid_IceBurst_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ice Burst", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Ice Burst", bonus)); break; case WheelGemSupremeModifier_t::Druid_EternalWinter_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Eternal Winter", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Eternal Winter", bonus)); break; case WheelGemSupremeModifier_t::Druid_EternalWinter_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Eternal Winter", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Eternal Winter", bonus)); break; case WheelGemSupremeModifier_t::Druid_TerraWave_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Wave", bonus)); + bonus.increase.damage = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Wave", bonus)); break; case WheelGemSupremeModifier_t::Druid_TerraWave_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Wave", bonus)); + bonus.increase.criticalDamage = 12 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Terra Wave", bonus)); break; case WheelGemSupremeModifier_t::Druid_StrongIceWave_DamageIncrease: - bonus.increase.damage = 25 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ice Wave", bonus)); + bonus.increase.damage = 8 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ice Wave", bonus)); break; case WheelGemSupremeModifier_t::Druid_StrongIceWave_CriticalExtraDamage: - bonus.increase.criticalDamage = 8 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ice Wave", bonus)); + bonus.increase.criticalDamage = 15 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Strong Ice Wave", bonus)); break; case WheelGemSupremeModifier_t::Druid_HealFriend_HealingIncrease: - bonus.increase.heal = 10 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Heal Friend", bonus)); + bonus.increase.heal = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Heal Friend", bonus)); break; case WheelGemSupremeModifier_t::Druid_MassHealing_HealingIncrease: - bonus.increase.heal = 10 * gradeMultiplier; - m_strategies.push_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Mass Healing", bonus)); + bonus.increase.heal = 5 * gradeMultiplier; + m_strategies.emplace_back(std::make_unique<GemModifierSpellBonusStrategy>(m_wheel, "Mass Healing", bonus)); break; default: g_logger().error("WheelModifierContext::setStrategy: Invalid supreme modifier: {}", static_cast<uint8_t>(modifier)); } } -void WheelModifierContext::executeStrategies() { - for (auto &strategy : m_strategies) { +void WheelModifierContext::executeStrategies() const { + for (const auto &strategy : m_strategies) { strategy->execute(); } } diff --git a/src/creatures/players/wheel/wheel_gems.hpp b/src/creatures/players/wheel/wheel_gems.hpp index dee64225183..7b748266781 100644 --- a/src/creatures/players/wheel/wheel_gems.hpp +++ b/src/creatures/players/wheel/wheel_gems.hpp @@ -32,7 +32,7 @@ class GemModifierStrategy { PlayerWheel &m_wheel; }; -class GemModifierResistanceStrategy : public GemModifierStrategy { +class GemModifierResistanceStrategy final : public GemModifierStrategy { public: explicit GemModifierResistanceStrategy(PlayerWheel &wheel, CombatType_t combatType, int32_t resistance) : GemModifierStrategy(wheel), @@ -46,7 +46,7 @@ class GemModifierResistanceStrategy : public GemModifierStrategy { int32_t m_resistance; }; -class GemModifierStatStrategy : public GemModifierStrategy { +class GemModifierStatStrategy final : public GemModifierStrategy { public: explicit GemModifierStatStrategy(PlayerWheel &wheel, WheelStat_t stat, int32_t value) : GemModifierStrategy(wheel), @@ -60,7 +60,7 @@ class GemModifierStatStrategy : public GemModifierStrategy { int32_t m_value {}; }; -class GemModifierRevelationStrategy : public GemModifierStrategy { +class GemModifierRevelationStrategy final : public GemModifierStrategy { public: explicit GemModifierRevelationStrategy(PlayerWheel &wheel, WheelGemAffinity_t affinity, [[maybe_unused]] uint16_t value) : GemModifierStrategy(wheel), @@ -74,9 +74,9 @@ class GemModifierRevelationStrategy : public GemModifierStrategy { uint16_t m_value {}; }; -class GemModifierSpellBonusStrategy : public GemModifierStrategy { +class GemModifierSpellBonusStrategy final : public GemModifierStrategy { public: - explicit GemModifierSpellBonusStrategy(PlayerWheel &wheel, std::string spellName, WheelSpells::Bonus bonus) : + explicit GemModifierSpellBonusStrategy(PlayerWheel &wheel, std::string spellName, const WheelSpells::Bonus &bonus) : GemModifierStrategy(wheel), m_spellName(std::move(spellName)), m_bonus(bonus) { } @@ -100,7 +100,7 @@ class WheelModifierContext { m_strategies.clear(); } - void executeStrategies(); + void executeStrategies() const; private: std::vector<std::unique_ptr<GemModifierStrategy>> m_strategies; diff --git a/src/database/database.cpp b/src/database/database.cpp index 37fe2b1a3c6..fcb7371708d 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -7,8 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ -#include "config/configmanager.hpp" #include "database/database.hpp" + +#include "config/configmanager.hpp" #include "lib/di/container.hpp" #include "lib/metrics/metrics.hpp" @@ -101,7 +102,7 @@ bool Database::commit() { return true; } -bool Database::isRecoverableError(unsigned int error) const { +bool Database::isRecoverableError(unsigned int error) { return error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR || error == CR_CONN_HOST_ERROR || error == 1053 /*ER_SERVER_SHUTDOWN*/ || error == CR_CONNECTION_ERROR; } @@ -225,10 +226,10 @@ std::string DBResult::getString(const std::string &s) const { auto it = listNames.find(s); if (it == listNames.end()) { g_logger().error("Column '{}' does not exist in result set", s); - return std::string(); + return {}; } if (row[it->second] == nullptr) { - return std::string(); + return {}; } return std::string(row[it->second]); } @@ -250,7 +251,7 @@ const char* DBResult::getStream(const std::string &s, unsigned long &size) const return row[it->second]; } -uint8_t DBResult::getU8FromString(const std::string &string, const std::string &function) const { +uint8_t DBResult::getU8FromString(const std::string &string, const std::string &function) { auto result = static_cast<uint8_t>(std::atoi(string.c_str())); if (result > std::numeric_limits<uint8_t>::max()) { g_logger().error("[{}] Failed to get number value {} for tier table result, on function call: {}", __FUNCTION__, result, function); @@ -260,7 +261,7 @@ uint8_t DBResult::getU8FromString(const std::string &string, const std::string & return result; } -int8_t DBResult::getInt8FromString(const std::string &string, const std::string &function) const { +int8_t DBResult::getInt8FromString(const std::string &string, const std::string &function) { auto result = static_cast<int8_t>(std::atoi(string.c_str())); if (result > std::numeric_limits<int8_t>::max()) { g_logger().error("[{}] Failed to get number value {} for tier table result, on function call: {}", __FUNCTION__, result, function); diff --git a/src/database/database.hpp b/src/database/database.hpp index 4984873ed62..69c47d324ad 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -14,6 +14,7 @@ #ifndef USE_PRECOMPILED_HEADERS #include <mysql/mysql.h> #include <mutex> + #include <utility> #endif class DBResult; @@ -62,7 +63,7 @@ class Database { bool rollback(); bool commit(); - bool isRecoverableError(unsigned int error) const; + static bool isRecoverableError(unsigned int error); MYSQL* handle = nullptr; std::recursive_mutex databaseLock; @@ -94,8 +95,19 @@ class DBResult { return T(); } - T data = 0; + T data {}; try { + // Check if the type T is a enum + if constexpr (std::is_enum_v<T>) { + using underlying_type = std::underlying_type_t<T>; + underlying_type value = 0; + if constexpr (std::is_signed_v<underlying_type>) { + value = static_cast<underlying_type>(std::stoll(row[it->second])); + } else { + value = static_cast<underlying_type>(std::stoull(row[it->second])); + } + return static_cast<T>(value); + } // Check if the type T is signed or unsigned if constexpr (std::is_signed_v<T>) { // Check if the type T is int8_t or int16_t @@ -148,8 +160,8 @@ class DBResult { std::string getString(const std::string &s) const; const char* getStream(const std::string &s, unsigned long &size) const; - uint8_t getU8FromString(const std::string &string, const std::string &function) const; - int8_t getInt8FromString(const std::string &string, const std::string &function) const; + static uint8_t getU8FromString(const std::string &string, const std::string &function); + static int8_t getInt8FromString(const std::string &string, const std::string &function); size_t countResults() const; bool hasNext() const; @@ -171,7 +183,7 @@ class DBInsert { public: explicit DBInsert(std::string query); void upsert(const std::vector<std::string> &columns); - bool addRow(const std::string_view row); + bool addRow(std::string_view row); bool addRow(std::ostringstream &row); bool execute(); @@ -198,16 +210,20 @@ class DBTransaction { template <typename Func> static bool executeWithinTransaction(const Func &toBeExecuted) { - DBTransaction transaction; - try { - transaction.begin(); - bool result = toBeExecuted(); - transaction.commit(); - return result; - } catch (const std::exception &exception) { - transaction.rollback(); - g_logger().error("[{}] Error occurred committing transaction, error: {}", __FUNCTION__, exception.what()); - return false; + bool changesExpected = toBeExecuted(); + if (changesExpected) { + DBTransaction transaction; + try { + transaction.begin(); + transaction.commit(); + return changesExpected; + } catch (const std::exception &exception) { + transaction.rollback(); + g_logger().error("[{}] Error occurred during transaction, error: {}", __FUNCTION__, exception.what()); + return false; + } + } else { + return true; } } @@ -279,10 +295,10 @@ class DBTransaction { class DatabaseException : public std::exception { public: - explicit DatabaseException(const std::string &message) : - message(message) { } + explicit DatabaseException(std::string message) : + message(std::move(message)) { } - virtual const char* what() const throw() { + const char* what() const noexcept override { return message.c_str(); } diff --git a/src/database/databasemanager.cpp b/src/database/databasemanager.cpp index 3d2d9c9fd64..2941172f35a 100644 --- a/src/database/databasemanager.cpp +++ b/src/database/databasemanager.cpp @@ -7,8 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ -#include "config/configmanager.hpp" #include "database/databasemanager.hpp" + +#include "config/configmanager.hpp" #include "lua/functions/core/libs/core_libs_functions.hpp" #include "lua/scripts/luascript.hpp" diff --git a/src/database/databasetasks.cpp b/src/database/databasetasks.cpp index 010b3f16320..afc4c3608f3 100644 --- a/src/database/databasetasks.cpp +++ b/src/database/databasetasks.cpp @@ -8,6 +8,7 @@ */ #include "database/databasetasks.hpp" + #include "game/scheduling/dispatcher.hpp" #include "lib/thread/thread_pool.hpp" #include "lib/di/container.hpp" @@ -20,7 +21,7 @@ DatabaseTasks &DatabaseTasks::getInstance() { return inject<DatabaseTasks>(); } -void DatabaseTasks::execute(const std::string &query, std::function<void(DBResult_ptr, bool)> callback /* nullptr */) { +void DatabaseTasks::execute(const std::string &query, const std::function<void(DBResult_ptr, bool)> &callback /* nullptr */) { threadPool.detach_task([this, query, callback]() { bool success = db.executeQuery(query); if (callback != nullptr) { @@ -29,7 +30,7 @@ void DatabaseTasks::execute(const std::string &query, std::function<void(DBResul }); } -void DatabaseTasks::store(const std::string &query, std::function<void(DBResult_ptr, bool)> callback /* nullptr */) { +void DatabaseTasks::store(const std::string &query, const std::function<void(DBResult_ptr, bool)> &callback /* nullptr */) { threadPool.detach_task([this, query, callback]() { DBResult_ptr result = db.storeQuery(query); if (callback != nullptr) { diff --git a/src/database/databasetasks.hpp b/src/database/databasetasks.hpp index 6922dfc566f..a9c86583db4 100644 --- a/src/database/databasetasks.hpp +++ b/src/database/databasetasks.hpp @@ -22,8 +22,8 @@ class DatabaseTasks { static DatabaseTasks &getInstance(); - void execute(const std::string &query, std::function<void(DBResult_ptr, bool)> callback = nullptr); - void store(const std::string &query, std::function<void(DBResult_ptr, bool)> callback = nullptr); + void execute(const std::string &query, const std::function<void(DBResult_ptr, bool)> &callback = nullptr); + void store(const std::string &query, const std::function<void(DBResult_ptr, bool)> &callback = nullptr); private: Database &db; diff --git a/src/enums/account_type.hpp b/src/enums/account_type.hpp index df76c4a289f..4929a32cfbf 100644 --- a/src/enums/account_type.hpp +++ b/src/enums/account_type.hpp @@ -14,6 +14,7 @@ #endif enum AccountType : uint8_t { + ACCOUNT_TYPE_NONE = 0, ACCOUNT_TYPE_NORMAL = 1, ACCOUNT_TYPE_TUTOR = 2, ACCOUNT_TYPE_SENIORTUTOR = 3, diff --git a/src/enums/item_attribute.hpp b/src/enums/item_attribute.hpp index be7b7445710..a3d76fde70f 100644 --- a/src/enums/item_attribute.hpp +++ b/src/enums/item_attribute.hpp @@ -9,7 +9,7 @@ #pragma once -enum ItemAttribute_t : uint64_t { +enum class ItemAttribute_t : uint64_t { NONE = 0, ACTIONID = 1, UNIQUEID = 2, diff --git a/src/enums/player_blessings.hpp b/src/enums/player_blessings.hpp index 086f04a6442..f71396f71b3 100644 --- a/src/enums/player_blessings.hpp +++ b/src/enums/player_blessings.hpp @@ -20,6 +20,6 @@ enum class Blessings : uint8_t { TheFireOfTheSuns = 4, TheSpiritualShielding = 5, TheEmbraceOfTibia = 6, - BloodOfTheMountain = 7, - HearthOfTheMountain = 8 + HearthOfTheMountain = 7, + BloodOfTheMountain = 8 }; diff --git a/src/enums/player_cyclopedia.hpp b/src/enums/player_cyclopedia.hpp index 295e573984f..af7ea1701ff 100644 --- a/src/enums/player_cyclopedia.hpp +++ b/src/enums/player_cyclopedia.hpp @@ -13,7 +13,7 @@ #include <cstdint> #endif -enum CyclopediaBadge_t : uint8_t { +enum class CyclopediaBadge_t : uint8_t { ACCOUNT_AGE = 1, LOYALTY, ACCOUNT_ALL_LEVEL, diff --git a/src/game/bank/bank.cpp b/src/game/bank/bank.cpp index b568d322810..c60852fe122 100644 --- a/src/game/bank/bank.cpp +++ b/src/game/bank/bank.cpp @@ -7,14 +7,15 @@ * Website: https://docs.opentibiabr.com/ */ -#include "bank.hpp" -#include "game/game.hpp" +#include "game/bank/bank.hpp" + +#include "config/configmanager.hpp" #include "creatures/players/player.hpp" -#include "io/iologindata.hpp" +#include "game/game.hpp" #include "game/scheduling/save_manager.hpp" #include "lib/metrics/metrics.hpp" -Bank::Bank(const std::shared_ptr<Bankable> bankable) : +Bank::Bank(const std::shared_ptr<Bankable> &bankable) : m_bankable(bankable) { } @@ -23,7 +24,7 @@ Bank::~Bank() { if (bankable == nullptr || bankable->isOnline()) { return; } - std::shared_ptr<Player> player = bankable->getPlayer(); + const auto &player = bankable->getPlayer(); if (player && !player->isOnline()) { g_saveManager().savePlayer(player); @@ -51,7 +52,7 @@ bool Bank::debit(uint64_t amount) { bool Bank::balance(uint64_t amount) const { auto bankable = getBankable(); if (!bankable) { - return 0; + return false; } bankable->setBankBalance(amount); return true; @@ -78,7 +79,7 @@ const std::set<std::string> deniedNames = { "paladinsample" }; -bool Bank::transferTo(const std::shared_ptr<Bank> &destination, const uint64_t amount) { +bool Bank::transferTo(const std::shared_ptr<Bank> &destination, uint64_t amount) { if (!destination) { g_logger().error("Bank::transferTo: destination is nullptr"); return false; @@ -138,11 +139,10 @@ bool Bank::transferTo(const std::shared_ptr<Bank> &destination, const uint64_t a return true; } -bool Bank::withdraw(std::shared_ptr<Player> player, uint64_t amount) { +bool Bank::withdraw(const std::shared_ptr<Player> &player, uint64_t amount) { if (!player) { return false; } - if (!debit(amount)) { return false; } @@ -151,7 +151,7 @@ bool Bank::withdraw(std::shared_ptr<Player> player, uint64_t amount) { return true; } -bool Bank::deposit(const std::shared_ptr<Bank> destination) { +bool Bank::deposit(const std::shared_ptr<Bank> &destination) { auto bankable = getBankable(); if (!bankable) { return false; @@ -163,7 +163,7 @@ bool Bank::deposit(const std::shared_ptr<Bank> destination) { return deposit(destination, amount); } -bool Bank::deposit(const std::shared_ptr<Bank> destination, uint64_t amount) { +bool Bank::deposit(const std::shared_ptr<Bank> &destination, uint64_t amount) { if (!destination) { return false; } diff --git a/src/game/bank/bank.hpp b/src/game/bank/bank.hpp index 7fdb740a022..7149d8ab0d0 100644 --- a/src/game/bank/bank.hpp +++ b/src/game/bank/bank.hpp @@ -29,7 +29,7 @@ class Bankable { class Bank : public SharedObject { public: - explicit Bank(const std::shared_ptr<Bankable> bankable); + explicit Bank(const std::shared_ptr<Bankable> &bankable); ~Bank() override; // Deleted copy constructor and assignment operator. @@ -42,10 +42,10 @@ class Bank : public SharedObject { bool balance(uint64_t amount) const; uint64_t balance(); bool hasBalance(uint64_t amount); - bool transferTo(const std::shared_ptr<Bank> &destination, const uint64_t amount); - bool withdraw(std::shared_ptr<Player> player, uint64_t amount); - bool deposit(const std::shared_ptr<Bank> destination); - bool deposit(const std::shared_ptr<Bank> destination, uint64_t amount); + bool transferTo(const std::shared_ptr<Bank> &destination, uint64_t amount); + bool withdraw(const std::shared_ptr<Player> &player, uint64_t amount); + bool deposit(const std::shared_ptr<Bank> &destination); + bool deposit(const std::shared_ptr<Bank> &destination, uint64_t amount); private: std::shared_ptr<Bankable> getBankable() const { diff --git a/src/game/functions/game_reload.cpp b/src/game/functions/game_reload.cpp index 2b699ce8df3..5de3e98b0b0 100644 --- a/src/game/functions/game_reload.cpp +++ b/src/game/functions/game_reload.cpp @@ -10,16 +10,27 @@ #include "game/functions/game_reload.hpp" #include "config/configmanager.hpp" -#include "lua/creature/events.hpp" +#include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/interactions/chat.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/npcs/npcs.hpp" #include "creatures/players/imbuements/imbuements.hpp" -#include "lua/scripts/lua_environment.hpp" +#include "game/game.hpp" +#include "game/zones/zone.hpp" +#include "lib/di/container.hpp" +#include "lua/creature/events.hpp" #include "lua/modules/modules.hpp" +#include "lua/scripts/lua_environment.hpp" #include "lua/scripts/scripts.hpp" -#include "game/zones/zone.hpp" +#include "creatures/players/vocations/vocation.hpp" GameReload::GameReload() = default; GameReload::~GameReload() = default; +GameReload &GameReload::getInstance() { + return inject<GameReload>(); +} + bool GameReload::init(Reload_t reloadTypes) { switch (reloadTypes) { case Reload_t::RELOAD_TYPE_ALL: @@ -126,7 +137,7 @@ bool GameReload::reloadOutfits() { } bool GameReload::reloadMounts() { - const bool result = g_game().mounts.reload(); + const bool result = g_game().mounts->reload(); logReloadStatus("Mounts", result); return result; } diff --git a/src/game/functions/game_reload.hpp b/src/game/functions/game_reload.hpp index 0f59046a9d4..4ef141c10aa 100644 --- a/src/game/functions/game_reload.hpp +++ b/src/game/functions/game_reload.hpp @@ -9,10 +9,6 @@ #pragma once -#include "game/game.hpp" - -class Game; - enum class Reload_t : uint8_t { RELOAD_TYPE_NONE, RELOAD_TYPE_ALL, @@ -37,7 +33,7 @@ enum class Reload_t : uint8_t { RELOAD_TYPE_LAST }; -class GameReload : public Game { +class GameReload { public: GameReload(); ~GameReload(); @@ -46,9 +42,7 @@ class GameReload : public Game { GameReload(const GameReload &) = delete; GameReload &operator=(const GameReload &) = delete; - static GameReload &getInstance() { - return inject<GameReload>(); - } + static GameReload &getInstance(); static bool init(Reload_t reloadType); static uint8_t getReloadNumber(Reload_t reloadTypes); diff --git a/src/game/game.cpp b/src/game/game.cpp index c6ba09311d5..7a492348649 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -9,55 +9,73 @@ #include "game/game.hpp" -#include "lua/creature/actions.hpp" -#include "items/bed.hpp" +#include "config/configmanager.hpp" +#include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/combat/spells.hpp" #include "creatures/creature.hpp" -#include "database/databasetasks.hpp" -#include "lua/creature/events.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" +#include "creatures/interactions/chat.hpp" +#include "creatures/monsters/monster.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/npcs/npc.hpp" +#include "creatures/players/achievement/player_achievement.hpp" +#include "creatures/players/cyclopedia/player_badge.hpp" +#include "creatures/players/cyclopedia/player_cyclopedia.hpp" +#include "creatures/players/grouping/party.hpp" +#include "creatures/players/grouping/team_finder.hpp" #include "creatures/players/highscore_category.hpp" +#include "creatures/players/imbuements/imbuements.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/vip/player_vip.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "enums/player_wheel.hpp" +#include "database/databasetasks.hpp" +#include "game/scheduling/dispatcher.hpp" +#include "game/scheduling/save_manager.hpp" #include "game/zones/zone.hpp" -#include "lua/global/globalevent.hpp" -#include "io/iologindata.hpp" +#include "io/io_bosstiary.hpp" #include "io/io_wheel.hpp" +#include "io/iobestiary.hpp" +#include "io/ioguild.hpp" +#include "io/iologindata.hpp" #include "io/iomarket.hpp" +#include "io/ioprey.hpp" +#include "items/bed.hpp" +#include "items/containers/inbox/inbox.hpp" +#include "items/containers/rewards/reward.hpp" +#include "items/containers/rewards/rewardchest.hpp" #include "items/items.hpp" -#include "lua/scripts/lua_environment.hpp" -#include "creatures/monsters/monster.hpp" -#include "lua/creature/movement.hpp" -#include "game/scheduling/dispatcher.hpp" -#include "game/scheduling/save_manager.hpp" -#include "server/server.hpp" -#include "creatures/combat/spells.hpp" +#include "items/items_classification.hpp" +#include "lua/callbacks/event_callback.hpp" +#include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/actions.hpp" +#include "lua/creature/creatureevent.hpp" +#include "lua/creature/events.hpp" #include "lua/creature/talkaction.hpp" -#include "items/weapons/weapons.hpp" -#include "creatures/players/imbuements/imbuements.hpp" -#include "creatures/players/wheel/player_wheel.hpp" -#include "enums/player_wheel.hpp" -#include "creatures/players/achievement/player_achievement.hpp" -#include "creatures/players/cyclopedia/player_badge.hpp" -#include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "creatures/players/cyclopedia/player_title.hpp" -#include "creatures/npcs/npc.hpp" -#include "server/network/webhook/webhook.hpp" +#include "lua/global/globalevent.hpp" +#include "lua/scripts/lua_environment.hpp" +#include "map/spectators.hpp" #include "server/network/protocol/protocollogin.hpp" #include "server/network/protocol/protocolstatus.hpp" -#include "map/spectators.hpp" +#include "server/network/protocol/protocolgame.hpp" +#include "server/network/webhook/webhook.hpp" +#include "server/server.hpp" #include "utils/tools.hpp" -#include "kv/kv.hpp" +#include "utils/wildcardtree.hpp" +#include "creatures/players/vocations/vocation.hpp" -#include "enums/object_category.hpp" -#include "enums/account_type.hpp" -#include "enums/account_group_type.hpp" -#include "enums/account_errors.hpp" #include "enums/account_coins.hpp" -#include "enums/player_blessings.hpp" +#include "enums/account_errors.hpp" +#include "enums/account_group_type.hpp" +#include "enums/account_type.hpp" +#include "enums/object_category.hpp" #include <appearances.pb.h> +std::vector<std::weak_ptr<Creature>> checkCreatureLists[EVENT_CREATURECOUNT]; + namespace InternalGame { - void sendBlockEffect(BlockType_t blockType, CombatType_t combatType, const Position &targetPos, std::shared_ptr<Creature> source) { + void sendBlockEffect(BlockType_t blockType, CombatType_t combatType, const Position &targetPos, const std::shared_ptr<Creature> &source) { if (blockType == BLOCK_DEFENSE) { g_game().addMagicEffect(targetPos, CONST_ME_POFF); } else if (blockType == BLOCK_ARMOR) { @@ -95,11 +113,11 @@ namespace InternalGame { } if (blockType != BLOCK_NONE) { - g_game().sendSingleSoundEffect(targetPos, SoundEffect_t::NO_DAMAGE, std::move(source)); + g_game().sendSingleSoundEffect(targetPos, SoundEffect_t::NO_DAMAGE, source); } } - bool playerCanUseItemOnHouseTile(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { + bool playerCanUseItemOnHouseTile(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { if (!player || !item) { return false; } @@ -136,7 +154,7 @@ namespace InternalGame { return true; } - bool playerCanUseItemWithOnHouseTile(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &toPos, int toStackPos, int toItemId) { + bool playerCanUseItemWithOnHouseTile(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const Position &toPos, int toStackPos, int toItemId) { if (!player || !item) { return false; } @@ -164,7 +182,7 @@ namespace InternalGame { } template <typename T> - T getCustomAttributeValue(std::shared_ptr<Item> item, const std::string &attributeName) { + T getCustomAttributeValue(const auto item, const std::string &attributeName) { static_assert(std::is_integral<T>::value, "T must be an integral type"); auto attribute = item->getCustomAttribute(attributeName); @@ -199,156 +217,162 @@ Game::Game() { wildcardTree = std::make_shared<WildcardTreeNode>(false); + mounts = std::make_unique<Mounts>(); + + using enum CyclopediaBadge_t; + using enum CyclopediaTitle_t; + using enum HighscoreCategories_t; + using enum BestiaryType_t; m_badges = { - Badge(1, CyclopediaBadge_t::ACCOUNT_AGE, "Fledegeling Hero", 1), - Badge(2, CyclopediaBadge_t::ACCOUNT_AGE, "Veteran Hero", 5), - Badge(3, CyclopediaBadge_t::ACCOUNT_AGE, "Senior Hero", 10), - Badge(4, CyclopediaBadge_t::ACCOUNT_AGE, "Ancient Hero", 15), - Badge(5, CyclopediaBadge_t::ACCOUNT_AGE, "Exalted Hero", 20), - - Badge(6, CyclopediaBadge_t::LOYALTY, "Tibia Loyalist (Grade 1)", 100), - Badge(7, CyclopediaBadge_t::LOYALTY, "Tibia Loyalist (Grade 2)", 1000), - Badge(8, CyclopediaBadge_t::LOYALTY, "Tibia Loyalist (Grade 3)", 5000), - - Badge(9, CyclopediaBadge_t::ACCOUNT_ALL_LEVEL, "Global Player (Grade 1)", 500), - Badge(10, CyclopediaBadge_t::ACCOUNT_ALL_LEVEL, "Global Player (Grade 2)", 1000), - Badge(11, CyclopediaBadge_t::ACCOUNT_ALL_LEVEL, "Global Player (Grade 3)", 2000), - - Badge(12, CyclopediaBadge_t::ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 1)", 100), - Badge(13, CyclopediaBadge_t::ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 2)", 250), - Badge(14, CyclopediaBadge_t::ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 3)", 500), - - Badge(15, CyclopediaBadge_t::TOURNAMENT_PARTICIPATION, "Freshman of the Tournament", 1), - Badge(16, CyclopediaBadge_t::TOURNAMENT_PARTICIPATION, "Regular of the Tournament", 5), - Badge(17, CyclopediaBadge_t::TOURNAMENT_PARTICIPATION, "Hero of the Tournament", 10), - - Badge(18, CyclopediaBadge_t::TOURNAMENT_POINTS, "Tournament Competitor", 1000), - Badge(19, CyclopediaBadge_t::TOURNAMENT_POINTS, "Tournament Challenger", 2500), - Badge(20, CyclopediaBadge_t::TOURNAMENT_POINTS, "Tournament Master", 5000), - Badge(21, CyclopediaBadge_t::TOURNAMENT_POINTS, "Tournament Champion", 10000), + Badge(1, ACCOUNT_AGE, "Fledegeling Hero", 1), + Badge(2, ACCOUNT_AGE, "Veteran Hero", 5), + Badge(3, ACCOUNT_AGE, "Senior Hero", 10), + Badge(4, ACCOUNT_AGE, "Ancient Hero", 15), + Badge(5, ACCOUNT_AGE, "Exalted Hero", 20), + + Badge(6, LOYALTY, "Tibia Loyalist (Grade 1)", 100), + Badge(7, LOYALTY, "Tibia Loyalist (Grade 2)", 1000), + Badge(8, LOYALTY, "Tibia Loyalist (Grade 3)", 5000), + + Badge(9, ACCOUNT_ALL_LEVEL, "Global Player (Grade 1)", 500), + Badge(10, ACCOUNT_ALL_LEVEL, "Global Player (Grade 2)", 1000), + Badge(11, ACCOUNT_ALL_LEVEL, "Global Player (Grade 3)", 2000), + + Badge(12, ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 1)", 100), + Badge(13, ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 2)", 250), + Badge(14, ACCOUNT_ALL_VOCATIONS, "Master Class (Grade 3)", 500), + + Badge(15, TOURNAMENT_PARTICIPATION, "Freshman of the Tournament", 1), + Badge(16, TOURNAMENT_PARTICIPATION, "Regular of the Tournament", 5), + Badge(17, TOURNAMENT_PARTICIPATION, "Hero of the Tournament", 10), + + Badge(18, TOURNAMENT_POINTS, "Tournament Competitor", 1000), + Badge(19, TOURNAMENT_POINTS, "Tournament Challenger", 2500), + Badge(20, TOURNAMENT_POINTS, "Tournament Master", 5000), + Badge(21, TOURNAMENT_POINTS, "Tournament Champion", 10000), }; m_titles = { - Title(1, CyclopediaTitle_t::GOLD, "Gold Hoarder", "Earned at least 1,000,000 gold.", 1000000, false), - Title(2, CyclopediaTitle_t::GOLD, "Platinum Hoarder", "Earned at least 10,000,000 gold.", 10000000, false), - Title(3, CyclopediaTitle_t::GOLD, "Crystal Hoarder", "Earned at least 100,000,000 gold.", 100000000, false), - - Title(4, CyclopediaTitle_t::MOUNTS, "Beaststrider (Grade 1)", "Unlocked 10 or more Mounts.", 10, true), - Title(5, CyclopediaTitle_t::MOUNTS, "Beaststrider (Grade 2)", "Unlocked 20 or more Mounts.", 20, true), - Title(6, CyclopediaTitle_t::MOUNTS, "Beaststrider (Grade 3)", "Unlocked 30 or more Mounts.", 30, true), - Title(7, CyclopediaTitle_t::MOUNTS, "Beaststrider (Grade 4)", "Unlocked 40 or more Mounts.", 40, true), - Title(8, CyclopediaTitle_t::MOUNTS, "Beaststrider (Grade 5)", "Unlocked 50 or more Mounts.", 50, true), - - Title(9, CyclopediaTitle_t::OUTFITS, "Tibia's Topmodel (Grade 1)", "Unlocked 10 or more Outfits.", 10, true), - Title(10, CyclopediaTitle_t::OUTFITS, "Tibia's Topmodel (Grade 2)", "Unlocked 20 or more Outfits.", 20, true), - Title(11, CyclopediaTitle_t::OUTFITS, "Tibia's Topmodel (Grade 3)", "Unlocked 30 or more Outfits.", 30, true), - Title(12, CyclopediaTitle_t::OUTFITS, "Tibia's Topmodel (Grade 4)", "Unlocked 40 or more Outfits.", 40, true), - Title(13, CyclopediaTitle_t::OUTFITS, "Tibia's Topmodel (Grade 5)", "Unlocked 50 or more Outfits.", 50, true), - - Title(14, CyclopediaTitle_t::LEVEL, "Trolltrasher", "Reached level 50.", 50, false), - Title(15, CyclopediaTitle_t::LEVEL, "Cyclopscamper", "Reached level 100.", 100, false), - Title(16, CyclopediaTitle_t::LEVEL, "Dragondouser", "Reached level 200.", 200, false), - Title(17, CyclopediaTitle_t::LEVEL, "Demondoom", "Reached level 300.", 300, false), - Title(18, CyclopediaTitle_t::LEVEL, "Drakenbane", "Reached level 400.", 400, false), - Title(19, CyclopediaTitle_t::LEVEL, "Silencer", "Reached level 500.", 500, false), - Title(20, CyclopediaTitle_t::LEVEL, "Exalted", "Reached level 1000.", 1000, false), - - Title(21, CyclopediaTitle_t::HIGHSCORES, "Apex Predator", "", "Highest Level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::EXPERIENCE)), - Title(22, CyclopediaTitle_t::HIGHSCORES, "Big Boss", "", "Highest score of accumulated boss points on character's world.", static_cast<uint8_t>(HighscoreCategories_t::BOSS_POINTS)), - Title(23, CyclopediaTitle_t::HIGHSCORES, "Jack of all Taints", "", "Highest score for killing Goshnar and his aspects on character's world.", static_cast<uint8_t>(HighscoreCategories_t::GOSHNAR)), - Title(24, CyclopediaTitle_t::HIGHSCORES, "Legend of Fishing", "", "Highest fishing level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::FISHING)), - Title(25, CyclopediaTitle_t::HIGHSCORES, "Legend of Magic", "", "Highest magic level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::MAGIC_LEVEL)), - Title(26, CyclopediaTitle_t::HIGHSCORES, "Legend of Marksmanship", "", "Highest distance level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::DISTANCE_FIGHTING)), - Title(27, CyclopediaTitle_t::HIGHSCORES, "Legend of the Axe", "", "Highest axe level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::AXE_FIGHTING)), - Title(28, CyclopediaTitle_t::HIGHSCORES, "Legend of the Club", "", "Highest club level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::CLUB_FIGHTING)), - Title(29, CyclopediaTitle_t::HIGHSCORES, "Legend of the Fist", "", "Highest fist level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::FIST_FIGHTING)), - Title(30, CyclopediaTitle_t::HIGHSCORES, "Legend of the Shield", "", "Highest shielding level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::SHIELDING)), - Title(31, CyclopediaTitle_t::HIGHSCORES, "Legend of the Sword", "", "Highest sword level on character's world.", static_cast<uint8_t>(HighscoreCategories_t::SWORD_FIGHTING)), - Title(32, CyclopediaTitle_t::HIGHSCORES, "Prince Charming", "Princess Charming", "Highest score of accumulated charm points on character's world.", static_cast<uint8_t>(HighscoreCategories_t::CHARMS)), - Title(33, CyclopediaTitle_t::HIGHSCORES, "Reigning Drome Champion", "", "Finished most recent Tibiadrome rota ranked in the top 5.", static_cast<uint8_t>(HighscoreCategories_t::DROME)), - - Title(34, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_HUMANOID), "Bipedantic", "", "Unlocked All Humanoid Bestiary entries."), - Title(35, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_LYCANTHROPE), "Blood Moon Hunter", "Blood Moon Huntress", "Unlocked All Lycanthrope Bestiary entries."), - Title(36, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_AMPHIBIC), "Coldblooded", "", "Unlocked All Amphibic Bestiary entries."), - Title(37, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_BIRD), "Death from Below", "", "Unlocked all Bird Bestiary entries."), - Title(38, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_DEMON), "Demonator", "", "Unlocked all Demon Bestiary entries."), - Title(39, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_DRAGON), "Dragonslayer", "", "Unlocked all Dragon Bestiary entries."), - Title(40, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_ELEMENTAL), "Elementalist", "", "Unlocked all Elemental Bestiary entries."), - Title(41, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_VERMIN), "Exterminator", "", "Unlocked all Vermin Bestiary entries."), - Title(42, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_FEY), "Fey Swatter", "", "Unlocked all Fey Bestiary entries."), - Title(43, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_UNDEAD), "Ghosthunter", "Ghosthuntress", "Unlocked all Undead Bestiary entries."), - Title(44, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_CONSTRUCT), "Handyman", "Handywoman", "Unlocked all Construct Bestiary entries."), - Title(45, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_MAMMAL), "Huntsman", "Huntress", "Unlocked all Mammal Bestiary entries."), - Title(46, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_EXTRA_DIMENSIONAL), "Interdimensional Destroyer", "", "Unlocked all Extra Dimensional Bestiary entries."), - Title(47, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_HUMAN), "Manhunter", "Manhuntress", "Unlocked all Human Bestiary entries."), - Title(48, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_MAGICAL), "Master of Illusion", "Mistress of Illusion", "Unlocked all Magical Bestiary entries."), - Title(49, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_SLIME), "Ooze Blues", "", "Unlocked all Slime Bestiary entries."), - Title(50, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_AQUATIC), "Sea Bane", "", "Unlocked all Aquatic Bestiary entries."), - Title(51, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_REPTILE), "Snake Charmer", "", "Unlocked all Reptile Bestiary entries."), - Title(52, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_GIANT), "Tumbler", "", "Unlocked all Giant Bestiary entries."), - Title(53, CyclopediaTitle_t::BESTIARY, static_cast<uint16_t>(BestiaryType_t::BESTY_RACE_PLANT), "Weedkiller", "", "Unlocked all Plant Bestiary entries."), - Title(54, CyclopediaTitle_t::BESTIARY, 0, "Executioner", "", "Unlocked all Bestiary entries."), - - Title(55, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Annihilator", "", "Unlocked all Nemesis bosses.", 0, false), - Title(56, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Destroyer", "", "Unlocked 10 or more Archfoe bosses.", 10, true), - Title(57, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Devastator", "", "Unlocked 10 or more Nemesis bosses.", 10, true), - Title(58, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Eraser", "", "Unlocked all Archfoe bosses.", 0, false), - Title(59, CyclopediaTitle_t::BOSSTIARY, 0, "Boss Executioner", "", "Unlocked all bosses.", 0, false), - Title(60, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Hunter", "", "Unlocked 10 or more Bane bosses.", 10, true), - Title(61, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Obliterator", "", "Unlocked 40 or more Nemesis bosses.", 40, true), - Title(62, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Slayer", "", "Unlocked all Bane bosses.", 0, false), - Title(63, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Smiter", "", "Unlocked 40 or more Archfoe bosses.", 40, true), - Title(64, CyclopediaTitle_t::BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Veteran", "", "Unlocked 40 or more Bane bosses.", 40, true), - - Title(65, CyclopediaTitle_t::DAILY_REWARD, "Creature of Habit (Grade 1)", "Reward Streak of at least 7 days of consecutive logins.", 7, true), - Title(66, CyclopediaTitle_t::DAILY_REWARD, "Creature of Habit (Grade 2)", "Reward Streak of at least 30 days of consecutive logins.", 30, true), - Title(67, CyclopediaTitle_t::DAILY_REWARD, "Creature of Habit (Grade 3)", "Reward Streak of at least 90 days of consecutive logins.", 90, true), - Title(68, CyclopediaTitle_t::DAILY_REWARD, "Creature of Habit (Grade 4)", "Reward Streak of at least 180 days of consecutive logins.", 180, true), - Title(69, CyclopediaTitle_t::DAILY_REWARD, "Creature of Habit (Grade 5)", "Reward Streak of at least 365 days of consecutive logins.", 365, true), - - Title(70, CyclopediaTitle_t::TASK, "Aspiring Huntsman", "Invested 160,000 tasks points.", 160000, true, "Aspiring Huntswoman"), - Title(71, CyclopediaTitle_t::TASK, "Competent Beastslayer", "Invested 320,000 tasks points.", 320000, true), - Title(72, CyclopediaTitle_t::TASK, "Feared Bountyhunter", "Invested 430,000 tasks points.", 430000, true), - - Title(73, CyclopediaTitle_t::MAP, "Dedicated Entrepreneur", "Explored 50% of all the map areas.", 50, false), - Title(74, CyclopediaTitle_t::MAP, "Globetrotter", "Explored all map areas.", 100, false), - - Title(75, CyclopediaTitle_t::OTHERS, "Guild Leader", "Leading a Guild.", false), - Title(76, CyclopediaTitle_t::OTHERS, "Proconsul of Iksupan", "Only a true devotee to the cause of the ancient Iks and their lost legacy may step up to the rank of proconsul.", true), - Title(77, CyclopediaTitle_t::OTHERS, "Admirer of the Crown", "Adjust your crown and handle it.", true), - Title(78, CyclopediaTitle_t::OTHERS, "Big Spender", "Unlocked the full Golden Outfit.", true), - Title(79, CyclopediaTitle_t::OTHERS, "Challenger of the Iks", "Challenged Ahau, guardian of Iksupan, in traditional Iks warrior attire.", true), - Title(80, CyclopediaTitle_t::OTHERS, "Royal Bounacean Advisor", "Called to the court of Bounac by Kesar the Younger himself.", true), - Title(81, CyclopediaTitle_t::OTHERS, "Aeternal", "Awarded exclusively to stalwart heroes keeping the faith under all circumstances.", true), - Title(82, CyclopediaTitle_t::OTHERS, "Robinson Crusoe", "Some discoveries are reserved to only the most experienced adventurers. Until the next frontier opens on the horizon.", true), - Title(83, CyclopediaTitle_t::OTHERS, "Chompmeister", "Awarded only to true connoisseurs undertaking even the most exotic culinary escapades.", true), - Title(84, CyclopediaTitle_t::OTHERS, "Bringer of Rain", "Forging through battle after battle like a true gladiator.", true), - Title(85, CyclopediaTitle_t::OTHERS, "Beastly", "Reached 2000 charm points. Quite beastly!", true), - Title(86, CyclopediaTitle_t::OTHERS, "Midnight Hunter", "When the hunter becomes the hunted, perseverance decides the game.", true), - Title(87, CyclopediaTitle_t::OTHERS, "Ratinator", "Killing some snarky cave rats is helpful, killing over ten thousand of them is a statement.", true), - Title(88, CyclopediaTitle_t::OTHERS, "Doomsday Nemesis", "Awarded for great help in the battle against Gaz'haragoth.", true), - Title(89, CyclopediaTitle_t::OTHERS, "Hero of Bounac", "You prevailed during the battle of Bounac and broke the siege that held Bounac's people in its firm grasp.", true), // Derrotar o boss Drume. - Title(90, CyclopediaTitle_t::OTHERS, "King of Demon", "Defeat Morshabaal 5 times.", 0, true, "Queen of Demon"), - Title(91, CyclopediaTitle_t::OTHERS, "Planegazer", "Followed the trail of the Planestrider to the end.", true), // Derrotar o boss Planestrider - Title(92, CyclopediaTitle_t::OTHERS, "Time Traveller", "Anywhere in time or space.", true), // Derrotar o boss Lord Retro - Title(93, CyclopediaTitle_t::OTHERS, "Truly Boss", "Reach 15,000 boss points.", true), + Title(1, GOLD, "Gold Hoarder", "Earned at least 1,000,000 gold.", 1000000, false), + Title(2, GOLD, "Platinum Hoarder", "Earned at least 10,000,000 gold.", 10000000, false), + Title(3, GOLD, "Crystal Hoarder", "Earned at least 100,000,000 gold.", 100000000, false), + + Title(4, MOUNTS, "Beaststrider (Grade 1)", "Unlocked 10 or more Mounts.", 10, true), + Title(5, MOUNTS, "Beaststrider (Grade 2)", "Unlocked 20 or more Mounts.", 20, true), + Title(6, MOUNTS, "Beaststrider (Grade 3)", "Unlocked 30 or more Mounts.", 30, true), + Title(7, MOUNTS, "Beaststrider (Grade 4)", "Unlocked 40 or more Mounts.", 40, true), + Title(8, MOUNTS, "Beaststrider (Grade 5)", "Unlocked 50 or more Mounts.", 50, true), + + Title(9, OUTFITS, "Tibia's Topmodel (Grade 1)", "Unlocked 10 or more Outfits.", 10, true), + Title(10, OUTFITS, "Tibia's Topmodel (Grade 2)", "Unlocked 20 or more Outfits.", 20, true), + Title(11, OUTFITS, "Tibia's Topmodel (Grade 3)", "Unlocked 30 or more Outfits.", 30, true), + Title(12, OUTFITS, "Tibia's Topmodel (Grade 4)", "Unlocked 40 or more Outfits.", 40, true), + Title(13, OUTFITS, "Tibia's Topmodel (Grade 5)", "Unlocked 50 or more Outfits.", 50, true), + + Title(14, LEVEL, "Trolltrasher", "Reached level 50.", 50, false), + Title(15, LEVEL, "Cyclopscamper", "Reached level 100.", 100, false), + Title(16, LEVEL, "Dragondouser", "Reached level 200.", 200, false), + Title(17, LEVEL, "Demondoom", "Reached level 300.", 300, false), + Title(18, LEVEL, "Drakenbane", "Reached level 400.", 400, false), + Title(19, LEVEL, "Silencer", "Reached level 500.", 500, false), + Title(20, LEVEL, "Exalted", "Reached level 1000.", 1000, false), + + Title(21, HIGHSCORES, "Apex Predator", "", "Highest Level on character's world.", static_cast<uint8_t>(EXPERIENCE)), + Title(22, HIGHSCORES, "Big Boss", "", "Highest score of accumulated boss points on character's world.", static_cast<uint8_t>(BOSS_POINTS)), + Title(23, HIGHSCORES, "Jack of all Taints", "", "Highest score for killing Goshnar and his aspects on character's world.", static_cast<uint8_t>(GOSHNAR)), + Title(24, HIGHSCORES, "Legend of Fishing", "", "Highest fishing level on character's world.", static_cast<uint8_t>(FISHING)), + Title(25, HIGHSCORES, "Legend of Magic", "", "Highest magic level on character's world.", static_cast<uint8_t>(MAGIC_LEVEL)), + Title(26, HIGHSCORES, "Legend of Marksmanship", "", "Highest distance level on character's world.", static_cast<uint8_t>(DISTANCE_FIGHTING)), + Title(27, HIGHSCORES, "Legend of the Axe", "", "Highest axe level on character's world.", static_cast<uint8_t>(AXE_FIGHTING)), + Title(28, HIGHSCORES, "Legend of the Club", "", "Highest club level on character's world.", static_cast<uint8_t>(CLUB_FIGHTING)), + Title(29, HIGHSCORES, "Legend of the Fist", "", "Highest fist level on character's world.", static_cast<uint8_t>(FIST_FIGHTING)), + Title(30, HIGHSCORES, "Legend of the Shield", "", "Highest shielding level on character's world.", static_cast<uint8_t>(SHIELDING)), + Title(31, HIGHSCORES, "Legend of the Sword", "", "Highest sword level on character's world.", static_cast<uint8_t>(SWORD_FIGHTING)), + Title(32, HIGHSCORES, "Prince Charming", "Princess Charming", "Highest score of accumulated charm points on character's world.", static_cast<uint8_t>(CHARMS)), + Title(33, HIGHSCORES, "Reigning Drome Champion", "", "Finished most recent Tibiadrome rota ranked in the top 5.", static_cast<uint8_t>(DROME)), + + Title(34, BESTIARY, static_cast<uint16_t>(BESTY_RACE_HUMANOID), "Bipedantic", "", "Unlocked All Humanoid Bestiary entries."), + Title(35, BESTIARY, static_cast<uint16_t>(BESTY_RACE_LYCANTHROPE), "Blood Moon Hunter", "Blood Moon Huntress", "Unlocked All Lycanthrope Bestiary entries."), + Title(36, BESTIARY, static_cast<uint16_t>(BESTY_RACE_AMPHIBIC), "Coldblooded", "", "Unlocked All Amphibic Bestiary entries."), + Title(37, BESTIARY, static_cast<uint16_t>(BESTY_RACE_BIRD), "Death from Below", "", "Unlocked all Bird Bestiary entries."), + Title(38, BESTIARY, static_cast<uint16_t>(BESTY_RACE_DEMON), "Demonator", "", "Unlocked all Demon Bestiary entries."), + Title(39, BESTIARY, static_cast<uint16_t>(BESTY_RACE_DRAGON), "Dragonslayer", "", "Unlocked all Dragon Bestiary entries."), + Title(40, BESTIARY, static_cast<uint16_t>(BESTY_RACE_ELEMENTAL), "Elementalist", "", "Unlocked all Elemental Bestiary entries."), + Title(41, BESTIARY, static_cast<uint16_t>(BESTY_RACE_VERMIN), "Exterminator", "", "Unlocked all Vermin Bestiary entries."), + Title(42, BESTIARY, static_cast<uint16_t>(BESTY_RACE_FEY), "Fey Swatter", "", "Unlocked all Fey Bestiary entries."), + Title(43, BESTIARY, static_cast<uint16_t>(BESTY_RACE_UNDEAD), "Ghosthunter", "Ghosthuntress", "Unlocked all Undead Bestiary entries."), + Title(44, BESTIARY, static_cast<uint16_t>(BESTY_RACE_CONSTRUCT), "Handyman", "Handywoman", "Unlocked all Construct Bestiary entries."), + Title(45, BESTIARY, static_cast<uint16_t>(BESTY_RACE_MAMMAL), "Huntsman", "Huntress", "Unlocked all Mammal Bestiary entries."), + Title(46, BESTIARY, static_cast<uint16_t>(BESTY_RACE_EXTRA_DIMENSIONAL), "Interdimensional Destroyer", "", "Unlocked all Extra Dimensional Bestiary entries."), + Title(47, BESTIARY, static_cast<uint16_t>(BESTY_RACE_HUMAN), "Manhunter", "Manhuntress", "Unlocked all Human Bestiary entries."), + Title(48, BESTIARY, static_cast<uint16_t>(BESTY_RACE_MAGICAL), "Master of Illusion", "Mistress of Illusion", "Unlocked all Magical Bestiary entries."), + Title(49, BESTIARY, static_cast<uint16_t>(BESTY_RACE_SLIME), "Ooze Blues", "", "Unlocked all Slime Bestiary entries."), + Title(50, BESTIARY, static_cast<uint16_t>(BESTY_RACE_AQUATIC), "Sea Bane", "", "Unlocked all Aquatic Bestiary entries."), + Title(51, BESTIARY, static_cast<uint16_t>(BESTY_RACE_REPTILE), "Snake Charmer", "", "Unlocked all Reptile Bestiary entries."), + Title(52, BESTIARY, static_cast<uint16_t>(BESTY_RACE_GIANT), "Tumbler", "", "Unlocked all Giant Bestiary entries."), + Title(53, BESTIARY, static_cast<uint16_t>(BESTY_RACE_PLANT), "Weedkiller", "", "Unlocked all Plant Bestiary entries."), + Title(54, BESTIARY, 0, "Executioner", "", "Unlocked all Bestiary entries."), + + Title(55, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Annihilator", "", "Unlocked all Nemesis bosses.", 0, false), + Title(56, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Destroyer", "", "Unlocked 10 or more Archfoe bosses.", 10, true), + Title(57, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Devastator", "", "Unlocked 10 or more Nemesis bosses.", 10, true), + Title(58, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Eraser", "", "Unlocked all Archfoe bosses.", 0, false), + Title(59, BOSSTIARY, 0, "Boss Executioner", "", "Unlocked all bosses.", 0, false), + Title(60, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Hunter", "", "Unlocked 10 or more Bane bosses.", 10, true), + Title(61, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_NEMESIS), "Boss Obliterator", "", "Unlocked 40 or more Nemesis bosses.", 40, true), + Title(62, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Slayer", "", "Unlocked all Bane bosses.", 0, false), + Title(63, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_ARCHFOE), "Boss Smiter", "", "Unlocked 40 or more Archfoe bosses.", 40, true), + Title(64, BOSSTIARY, static_cast<uint16_t>(BosstiaryRarity_t::RARITY_BANE), "Boss Veteran", "", "Unlocked 40 or more Bane bosses.", 40, true), + + Title(65, DAILY_REWARD, "Creature of Habit (Grade 1)", "Reward Streak of at least 7 days of consecutive logins.", 7, true), + Title(66, DAILY_REWARD, "Creature of Habit (Grade 2)", "Reward Streak of at least 30 days of consecutive logins.", 30, true), + Title(67, DAILY_REWARD, "Creature of Habit (Grade 3)", "Reward Streak of at least 90 days of consecutive logins.", 90, true), + Title(68, DAILY_REWARD, "Creature of Habit (Grade 4)", "Reward Streak of at least 180 days of consecutive logins.", 180, true), + Title(69, DAILY_REWARD, "Creature of Habit (Grade 5)", "Reward Streak of at least 365 days of consecutive logins.", 365, true), + + Title(70, TASK, "Aspiring Huntsman", "Invested 160,000 tasks points.", 160000, true, "Aspiring Huntswoman"), + Title(71, TASK, "Competent Beastslayer", "Invested 320,000 tasks points.", 320000, true), + Title(72, TASK, "Feared Bountyhunter", "Invested 430,000 tasks points.", 430000, true), + + Title(73, MAP, "Dedicated Entrepreneur", "Explored 50% of all the map areas.", 50, false), + Title(74, MAP, "Globetrotter", "Explored all map areas.", 100, false), + + Title(75, OTHERS, "Guild Leader", "Leading a Guild.", false), + Title(76, OTHERS, "Proconsul of Iksupan", "Only a true devotee to the cause of the ancient Iks and their lost legacy may step up to the rank of proconsul.", true), + Title(77, OTHERS, "Admirer of the Crown", "Adjust your crown and handle it.", true), + Title(78, OTHERS, "Big Spender", "Unlocked the full Golden Outfit.", true), + Title(79, OTHERS, "Challenger of the Iks", "Challenged Ahau, guardian of Iksupan, in traditional Iks warrior attire.", true), + Title(80, OTHERS, "Royal Bounacean Advisor", "Called to the court of Bounac by Kesar the Younger himself.", true), + Title(81, OTHERS, "Aeternal", "Awarded exclusively to stalwart heroes keeping the faith under all circumstances.", true), + Title(82, OTHERS, "Robinson Crusoe", "Some discoveries are reserved to only the most experienced adventurers. Until the next frontier opens on the horizon.", true), + Title(83, OTHERS, "Chompmeister", "Awarded only to true connoisseurs undertaking even the most exotic culinary escapades.", true), + Title(84, OTHERS, "Bringer of Rain", "Forging through battle after battle like a true gladiator.", true), + Title(85, OTHERS, "Beastly", "Reached 2000 charm points. Quite beastly!", true), + Title(86, OTHERS, "Midnight Hunter", "When the hunter becomes the hunted, perseverance decides the game.", true), + Title(87, OTHERS, "Ratinator", "Killing some snarky cave rats is helpful, killing over ten thousand of them is a statement.", true), + Title(88, OTHERS, "Doomsday Nemesis", "Awarded for great help in the battle against Gaz'haragoth.", true), + Title(89, OTHERS, "Hero of Bounac", "You prevailed during the battle of Bounac and broke the siege that held Bounac's people in its firm grasp.", true), // Derrotar o boss Drume. + Title(90, OTHERS, "King of Demon", "Defeat Morshabaal 5 times.", 0, true, "Queen of Demon"), + Title(91, OTHERS, "Planegazer", "Followed the trail of the Planestrider to the end.", true), // Derrotar o boss Planestrider + Title(92, OTHERS, "Time Traveller", "Anywhere in time or space.", true), // Derrotar o boss Lord Retro + Title(93, OTHERS, "Truly Boss", "Reach 15,000 boss points.", true), }; m_highscoreCategoriesNames = { - { static_cast<uint8_t>(HighscoreCategories_t::ACHIEVEMENTS), "Achievement Points" }, - { static_cast<uint8_t>(HighscoreCategories_t::AXE_FIGHTING), "Axe Fighting" }, - { static_cast<uint8_t>(HighscoreCategories_t::BOSS_POINTS), "Boss Points" }, - { static_cast<uint8_t>(HighscoreCategories_t::CHARMS), "Charm Points" }, - { static_cast<uint8_t>(HighscoreCategories_t::CLUB_FIGHTING), "Club Fighting" }, - { static_cast<uint8_t>(HighscoreCategories_t::DISTANCE_FIGHTING), "Distance Fighting" }, - { static_cast<uint8_t>(HighscoreCategories_t::DROME), "Drome Score" }, - { static_cast<uint8_t>(HighscoreCategories_t::EXPERIENCE), "Experience Points" }, - { static_cast<uint8_t>(HighscoreCategories_t::FISHING), "Fishing" }, - { static_cast<uint8_t>(HighscoreCategories_t::FIST_FIGHTING), "Fist Fighting" }, - { static_cast<uint8_t>(HighscoreCategories_t::GOSHNAR), "Goshnar's Taint" }, - { static_cast<uint8_t>(HighscoreCategories_t::LOYALTY), "Loyalty Points" }, - { static_cast<uint8_t>(HighscoreCategories_t::MAGIC_LEVEL), "Magic Level" }, - { static_cast<uint8_t>(HighscoreCategories_t::SHIELDING), "Shielding" }, + { static_cast<uint8_t>(ACHIEVEMENTS), "Achievement Points" }, + { static_cast<uint8_t>(AXE_FIGHTING), "Axe Fighting" }, + { static_cast<uint8_t>(BOSS_POINTS), "Boss Points" }, + { static_cast<uint8_t>(CHARMS), "Charm Points" }, + { static_cast<uint8_t>(CLUB_FIGHTING), "Club Fighting" }, + { static_cast<uint8_t>(DISTANCE_FIGHTING), "Distance Fighting" }, + { static_cast<uint8_t>(DROME), "Drome Score" }, + { static_cast<uint8_t>(EXPERIENCE), "Experience Points" }, + { static_cast<uint8_t>(FISHING), "Fishing" }, + { static_cast<uint8_t>(FIST_FIGHTING), "Fist Fighting" }, + { static_cast<uint8_t>(GOSHNAR), "Goshnar's Taint" }, + { static_cast<uint8_t>(LOYALTY_POINTS), "Loyalty Points" }, + { static_cast<uint8_t>(MAGIC_LEVEL), "Magic Level" }, + { static_cast<uint8_t>(SHIELDING), "Shielding" }, { static_cast<uint8_t>(HighscoreCategories_t::SWORD_FIGHTING), "Sword Fighting" }, }; @@ -395,6 +419,10 @@ Game::Game() { Game::~Game() = default; +Game &Game::getInstance() { + return inject<Game>(); +} + void Game::resetMonsters() const { for (const auto &[monsterId, monster] : getMonsters()) { monster->clearTargetList(); @@ -419,8 +447,8 @@ void Game::loadBoostedCreature() { return; } - const uint16_t date = result->getNumber<uint16_t>("date"); - const time_t now = time(0); + const auto date = result->getNumber<uint16_t>("date"); + const auto now = getTimeNow(); tm* ltm = localtime(&now); if (date == ltm->tm_mday) { @@ -428,7 +456,7 @@ void Game::loadBoostedCreature() { return; } - const uint16_t oldRace = result->getNumber<uint16_t>("raceid"); + const auto oldRace = result->getNumber<uint16_t>("raceid"); const auto monsterlist = getBestiaryList(); struct MonsterRace { @@ -493,7 +521,7 @@ void Game::start(ServiceManager* manager) { serviceManager = manager; - time_t now = time(0); + const auto now = getTimeNow(); const tm* tms = localtime(&now); int minutes = tms->tm_min; lightHour = (minutes * LIGHT_DAY_LENGTH) / 60; @@ -529,6 +557,10 @@ void Game::start(ServiceManager* manager) { marketItemsPriceIntervalMS, [this] { loadItemsPrice(); }, "Game::loadItemsPrice" ); } + + g_dispatcher().cycleEvent( + UPDATE_PLAYERS_ONLINE_DB, [this] { updatePlayersOnline(); }, "Game::updatePlayersOnline" + ); } GameState_t Game::getGameState() const { @@ -539,6 +571,28 @@ void Game::setWorldType(WorldType_t type) { worldType = type; } +const std::unique_ptr<TeamFinder> &Game::getTeamFinder(const std::shared_ptr<Player> &player) const { + auto it = teamFinderMap.find(player->getGUID()); + if (it != teamFinderMap.end()) { + return it->second; + } + + return TeamFinderNull; +} + +const std::unique_ptr<TeamFinder> &Game::getOrCreateTeamFinder(const std::shared_ptr<Player> &player) { + auto it = teamFinderMap.find(player->getGUID()); + if (it != teamFinderMap.end()) { + return it->second; + } + + return teamFinderMap[player->getGUID()] = std::make_unique<TeamFinder>(); +} + +void Game::removeTeamFinderListed(uint32_t leaderGuid) { + teamFinderMap.erase(leaderGuid); +} + void Game::setGameState(GameState_t newState) { if (gameState == GAME_STATE_SHUTDOWN) { return; // this cannot be stopped @@ -569,7 +623,7 @@ void Game::setGameState(GameState_t newState) { raids.loadFromXml(); raids.startup(); - mounts.loadFromXml(); + mounts->loadFromXml(); loadMotdNum(); loadPlayersRecord(); @@ -638,7 +692,7 @@ void Game::loadItemsPrice() { } // Update active buy offers (market_offers) - auto offers = IOMarket::getInstance().getActiveOffers(MARKETACTION_BUY); + auto offers = IOMarket::getActiveOffers(MARKETACTION_BUY); for (const auto &offer : offers) { itemsPriceMap[offer.itemId][offer.tier] = std::max(itemsPriceMap[offer.itemId][offer.tier], offer.price); } @@ -701,7 +755,7 @@ void Game::loadMap(const std::string &path, const Position &pos) { map.loadMap(path, false, false, false, false, false, pos); } -std::shared_ptr<Cylinder> Game::internalGetCylinder(std::shared_ptr<Player> player, const Position &pos) { +std::shared_ptr<Cylinder> Game::internalGetCylinder(const std::shared_ptr<Player> &player, const Position &pos) { if (pos.x != 0xFFFF) { return map.getTile(pos); } @@ -716,7 +770,7 @@ std::shared_ptr<Cylinder> Game::internalGetCylinder(std::shared_ptr<Player> play return player; } -std::shared_ptr<Thing> Game::internalGetThing(std::shared_ptr<Player> player, const Position &pos, int32_t index, uint32_t itemId, StackPosType_t type) { +std::shared_ptr<Thing> Game::internalGetThing(const std::shared_ptr<Player> &player, const Position &pos, int32_t index, uint32_t itemId, StackPosType_t type) { if (pos.x != 0xFFFF) { std::shared_ptr<Tile> tile = map.getTile(pos); if (!tile) { @@ -730,7 +784,7 @@ std::shared_ptr<Thing> Game::internalGetThing(std::shared_ptr<Player> player, co } case STACKPOS_MOVE: { - std::shared_ptr<Item> item = tile->getTopDownItem(); + const auto &item = tile->getTopDownItem(); if (item && item->isMovable()) { thing = item; } else { @@ -797,13 +851,13 @@ std::shared_ptr<Thing> Game::internalGetThing(std::shared_ptr<Player> player, co if (pos.y & 0x40) { uint8_t fromCid = pos.y & 0x0F; - std::shared_ptr<Container> parentContainer = player->getContainerByID(fromCid); + const std::shared_ptr<Container> &parentContainer = player->getContainerByID(fromCid); if (!parentContainer) { return nullptr; } if (parentContainer->getID() == ITEM_BROWSEFIELD) { - std::shared_ptr<Tile> tile = parentContainer->getTile(); + const std::shared_ptr<Tile> &tile = parentContainer->getTile(); if (tile && tile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { if (tile->hasProperty(CONST_PROP_ISVERTICAL)) { if (player->getPosition().x + 1 == tile->getPosition().x) { @@ -851,11 +905,11 @@ std::shared_ptr<Thing> Game::internalGetThing(std::shared_ptr<Player> player, co } // inventory - Slots_t slot = static_cast<Slots_t>(pos.y); + auto slot = static_cast<Slots_t>(pos.y); return player->getInventoryItem(slot); } -void Game::internalGetPosition(std::shared_ptr<Item> item, Position &pos, uint8_t &stackpos) { +void Game::internalGetPosition(const std::shared_ptr<Item> &item, Position &pos, uint8_t &stackpos) { pos.x = 0; pos.y = 0; pos.z = 0; @@ -863,10 +917,10 @@ void Game::internalGetPosition(std::shared_ptr<Item> item, Position &pos, uint8_ std::shared_ptr<Cylinder> topParent = item->getTopParent(); if (topParent) { - if (std::shared_ptr<Player> player = std::dynamic_pointer_cast<Player>(topParent)) { + if (const auto &player = std::dynamic_pointer_cast<Player>(topParent)) { pos.x = 0xFFFF; - std::shared_ptr<Container> container = std::dynamic_pointer_cast<Container>(item->getParent()); + const std::shared_ptr<Container> &container = std::dynamic_pointer_cast<Container>(item->getParent()); if (container) { pos.y = static_cast<uint16_t>(0x40) | static_cast<uint16_t>(player->getContainerID(container)); pos.z = container->getThingIndex(item); @@ -875,7 +929,7 @@ void Game::internalGetPosition(std::shared_ptr<Item> item, Position &pos, uint8_ pos.y = player->getThingIndex(item); stackpos = pos.y; } - } else if (std::shared_ptr<Tile> tile = topParent->getTile()) { + } else if (const std::shared_ptr<Tile> &tile = topParent->getTile()) { pos = tile->getPosition(); stackpos = tile->getThingIndex(item); } @@ -1062,9 +1116,9 @@ ReturnValue Game::getPlayerByNameWildcard(const std::string &s, std::shared_ptr< return RETURNVALUE_NOERROR; } -std::vector<std::shared_ptr<Player>> Game::getPlayersByAccount(std::shared_ptr<Account> acc, bool allowOffline /* = false */) { +std::vector<std::shared_ptr<Player>> Game::getPlayersByAccount(const std::shared_ptr<Account> &acc, bool allowOffline /* = false */) { auto [accountPlayers, error] = acc->getAccountPlayers(); - if (error != enumToValue(AccountErrors_t::Ok)) { + if (error != AccountErrors_t::Ok) { return {}; } std::vector<std::shared_ptr<Player>> ret; @@ -1077,7 +1131,7 @@ std::vector<std::shared_ptr<Player>> Game::getPlayersByAccount(std::shared_ptr<A return ret; } -bool Game::internalPlaceCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos /*=false*/, bool forced /*= false*/, bool creatureCheck /*= false*/) { +bool Game::internalPlaceCreature(const std::shared_ptr<Creature> &creature, const Position &pos, bool extendedPos /*=false*/, bool forced /*= false*/, bool creatureCheck /*= false*/) { if (creature->getParent() != nullptr) { return false; } @@ -1106,8 +1160,8 @@ bool Game::internalPlaceCreature(std::shared_ptr<Creature> creature, const Posit return true; } -bool Game::placeCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos /*=false*/, bool forced /*= false*/) { - metrics::method_latency measure(__METHOD_NAME__); +bool Game::placeCreature(const std::shared_ptr<Creature> &creature, const Position &pos, bool extendedPos /*=false*/, bool forced /*= false*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (!internalPlaceCreature(creature, pos, extendedPos, forced)) { return false; } @@ -1133,8 +1187,8 @@ bool Game::placeCreature(std::shared_ptr<Creature> creature, const Position &pos return true; } -bool Game::removeCreature(std::shared_ptr<Creature> creature, bool isLogout /* = true*/) { - metrics::method_latency measure(__METHOD_NAME__); +bool Game::removeCreature(const std::shared_ptr<Creature> &creature, bool isLogout /* = true*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (!creature || creature->isRemoved()) { return false; } @@ -1202,7 +1256,7 @@ bool Game::removeCreature(std::shared_ptr<Creature> creature, bool isLogout /* = } void Game::executeDeath(uint32_t creatureId) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); std::shared_ptr<Creature> creature = getCreatureByID(creatureId); if (creature && !creature->isRemoved()) { afterCreatureZoneChange(creature, creature->getZones(), {}); @@ -1211,8 +1265,8 @@ void Game::executeDeath(uint32_t creatureId) { } void Game::playerTeleport(uint32_t playerId, const Position &newPosition) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player || !player->hasFlag(PlayerFlags_t::CanMapClickTeleport)) { return; } @@ -1223,15 +1277,15 @@ void Game::playerTeleport(uint32_t playerId, const Position &newPosition) { } } -void Game::playerInspectItem(std::shared_ptr<Player> player, const Position &pos) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Thing> thing = internalGetThing(player, pos, 0, 0, STACKPOS_TOPDOWN_ITEM); +void Game::playerInspectItem(const std::shared_ptr<Player> &player, const Position &pos) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, 0, 0, STACKPOS_TOPDOWN_ITEM); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -1240,8 +1294,8 @@ void Game::playerInspectItem(std::shared_ptr<Player> player, const Position &pos player->sendItemInspection(item->getID(), static_cast<uint8_t>(item->getItemCount()), item, false); } -void Game::playerInspectItem(std::shared_ptr<Player> player, uint16_t itemId, uint8_t itemCount, bool cyclopedia) { - metrics::method_latency measure(__METHOD_NAME__); +void Game::playerInspectItem(const std::shared_ptr<Player> &player, uint16_t itemId, uint8_t itemCount, bool cyclopedia) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); player->sendItemInspection(itemId, itemCount, nullptr, cyclopedia); } @@ -1295,8 +1349,8 @@ FILELOADER_ERRORS Game::loadAppearanceProtobuf(const std::string &file) { } void Game::playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -1323,14 +1377,14 @@ void Game::playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t fromIndex = fromStackPos; } - std::shared_ptr<Thing> thing = internalGetThing(player, fromPos, fromIndex, itemId, STACKPOS_MOVE); + const std::shared_ptr<Thing> &thing = internalGetThing(player, fromPos, fromIndex, itemId, STACKPOS_MOVE); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - if (std::shared_ptr<Creature> movingCreature = thing->getCreature()) { - std::shared_ptr<Tile> tile = map.getTile(toPos); + if (const std::shared_ptr<Creature> &movingCreature = thing->getCreature()) { + const std::shared_ptr<Tile> &tile = map.getTile(toPos); if (!tile) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -1360,12 +1414,12 @@ void Game::playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t } void Game::playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, const Position &movingCreatureOrigPos, const Position &toPos) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Creature> movingCreature = getCreatureByID(movingCreatureId); + const auto &movingCreature = getCreatureByID(movingCreatureId); if (!movingCreature) { return; } @@ -1379,8 +1433,8 @@ void Game::playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, playerMoveCreature(player, movingCreature, movingCreatureOrigPos, toTile); } -void Game::playerMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> movingCreature, const Position &movingCreatureOrigPos, std::shared_ptr<Tile> toTile) { - metrics::method_latency measure(__METHOD_NAME__); +void Game::playerMoveCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &movingCreature, const Position &movingCreatureOrigPos, const std::shared_ptr<Tile> &toTile) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); g_dispatcher().addWalkEvent([=, this] { if (!player->canDoAction()) { @@ -1481,7 +1535,7 @@ void Game::playerMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Cr }); } -ReturnValue Game::internalMoveCreature(std::shared_ptr<Creature> creature, Direction direction, uint32_t flags /*= 0*/) { +ReturnValue Game::internalMoveCreature(const std::shared_ptr<Creature> &creature, Direction direction, uint32_t flags /*= 0*/) { if (!creature) { return RETURNVALUE_NOTPOSSIBLE; } @@ -1493,7 +1547,7 @@ ReturnValue Game::internalMoveCreature(std::shared_ptr<Creature> creature, Direc creature->setLastPosition(creature->getPosition()); const Position ¤tPos = creature->getPosition(); Position destPos = getNextPosition(direction, currentPos); - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); bool diagonalMovement = (direction & DIRECTION_DIAGONAL_MASK) != 0; if (player && !diagonalMovement) { @@ -1536,7 +1590,7 @@ ReturnValue Game::internalMoveCreature(std::shared_ptr<Creature> creature, Direc } ReturnValue Game::internalMoveCreature(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &toTile, uint32_t flags /*= 0*/) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (creature->hasCondition(CONDITION_ROOTED)) { return RETURNVALUE_NOTPOSSIBLE; } @@ -1566,7 +1620,11 @@ ReturnValue Game::internalMoveCreature(const std::shared_ptr<Creature> &creature std::shared_ptr<Tile> fromCylinder = nullptr; uint32_t n = 0; - while ((subCylinder = toCylinder->queryDestination(index, creature, &toItem, flags)->getTile()) != toCylinder) { + while ((subCylinder = toCylinder->queryDestination(index, creature, toItem, flags)->getTile()) != toCylinder) { + if (subCylinder == nullptr) { + break; + } + map.moveCreature(creature, subCylinder); if (creature->getParent() != subCylinder) { @@ -1600,16 +1658,16 @@ ReturnValue Game::internalMoveCreature(const std::shared_ptr<Creature> &creature } void Game::playerMoveItemByPlayerID(uint32_t playerId, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } playerMoveItem(player, fromPos, itemId, fromStackPos, toPos, count, nullptr, nullptr); } -void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr<Item> item, std::shared_ptr<Cylinder> toCylinder) { +void Game::playerMoveItem(const std::shared_ptr<Player> &player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr<Item> item, std::shared_ptr<Cylinder> toCylinder) { if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); + const uint32_t delay = player->getNextActionTime(); const auto &task = createPlayerTask( delay, [this, playerId = player->getID(), fromPos, itemId, fromStackPos, toPos, count] { @@ -1641,7 +1699,7 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo fromIndex = fromStackPos; } - std::shared_ptr<Thing> thing = internalGetThing(player, fromPos, fromIndex, itemId, STACKPOS_MOVE); + const auto &thing = internalGetThing(player, fromPos, fromIndex, itemId, STACKPOS_MOVE); if (!thing || !thing->getItem()) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -1684,14 +1742,14 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo } // check if we can move this item - if (ReturnValue ret = checkMoveItemToCylinder(player, fromCylinder, toCylinder, item, toPos); ret != RETURNVALUE_NOERROR) { + if (auto ret = checkMoveItemToCylinder(player, fromCylinder, toCylinder, item, toPos); ret != RETURNVALUE_NOERROR) { player->sendCancelMessage(ret); return; } - const Position &playerPos = player->getPosition(); - auto cylinderTile = fromCylinder->getTile(); - const Position &mapFromPos = cylinderTile ? cylinderTile->getPosition() : item->getPosition(); + const auto &playerPos = player->getPosition(); + const auto &cylinderTile = fromCylinder->getTile(); + const auto &mapFromPos = cylinderTile ? cylinderTile->getPosition() : item->getPosition(); if (playerPos.z != mapFromPos.z) { player->sendCancelMessage(playerPos.z > mapFromPos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS); return; @@ -1716,8 +1774,8 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo return; } - std::shared_ptr<Tile> toCylinderTile = toCylinder->getTile(); - const Position &mapToPos = toCylinderTile->getPosition(); + const auto toCylinderTile = toCylinder->getTile(); + const auto &mapToPos = toCylinderTile->getPosition(); // hangable item specific code if (item->isHangable() && toCylinderTile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { @@ -1736,14 +1794,14 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo } if (!Position::areInRange<1, 1, 0>(playerPos, mapToPos)) { - Position walkPos = mapToPos; + auto walkPos = mapToPos; if (vertical) { walkPos.x++; } else { walkPos.y++; } - Position itemPos = fromPos; + auto itemPos = fromPos; uint8_t itemStackPos = fromStackPos; if (fromPos.x != 0xFFFF && Position::areInRange<1, 1>(mapFromPos, playerPos) @@ -1751,7 +1809,7 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo // need to pickup the item first std::shared_ptr<Item> moveItem = nullptr; - ReturnValue ret = internalMoveItem(fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem); + const auto ret = internalMoveItem(fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem); if (ret != RETURNVALUE_NOERROR) { player->sendCancelMessage(ret); return; @@ -1779,7 +1837,7 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo } } - auto throwRange = item->getThrowRange(); + const auto throwRange = item->getThrowRange(); if ((Position::getDistanceX(playerPos, mapToPos) > throwRange) || (Position::getDistanceY(playerPos, mapToPos) > throwRange) || (Position::getDistanceZ(mapFromPos, mapToPos) * 4 > throwRange)) { player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH); return; @@ -1808,8 +1866,8 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo } if (item->isWrapable() || item->isStoreItem() || (item->hasOwner() && !item->isOwner(player))) { - auto toHouseTile = map.getTile(mapToPos)->dynamic_self_cast<HouseTile>(); - auto fromHouseTile = map.getTile(mapFromPos)->dynamic_self_cast<HouseTile>(); + const auto toHouseTile = map.getTile(mapToPos)->dynamic_self_cast<HouseTile>(); + const auto fromHouseTile = map.getTile(mapFromPos)->dynamic_self_cast<HouseTile>(); if (fromHouseTile && (!toHouseTile || toHouseTile->getHouse()->getId() != fromHouseTile->getHouse()->getId())) { player->sendCancelMessage("You cannot move this item out of this house."); return; @@ -1824,12 +1882,14 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo player->sendCancelMessage(RETURNVALUE_NOTMOVABLE); return; } - ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player); + + const auto ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player); if (ret != RETURNVALUE_NOERROR) { player->sendCancelMessage(ret); } else if (toCylinder->getContainer() && fromCylinder->getContainer() && fromCylinder->getContainer()->countsToLootAnalyzerBalance() && toCylinder->getContainer()->getTopParent() == player) { player->sendLootStats(item, count); } + player->cancelPush(); item->checkDecayMapItemOnMove(); @@ -1838,11 +1898,11 @@ void Game::playerMoveItem(std::shared_ptr<Player> player, const Position &fromPo g_callbacks().executeCallback(EventCallback_t::playerOnItemMoved, &EventCallback::playerOnItemMoved, player, item, count, fromPos, toPos, fromCylinder, toCylinder); } -bool Game::isTryingToStow(const Position &toPos, std::shared_ptr<Cylinder> toCylinder) const { +bool Game::isTryingToStow(const Position &toPos, const std::shared_ptr<Cylinder> &toCylinder) const { return toCylinder->getContainer() && toCylinder->getItem()->getID() == ITEM_LOCKER && toPos.getZ() == ITEM_SUPPLY_STASH_INDEX; } -ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr<Player> player, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, Position toPos) { +ReturnValue Game::checkMoveItemToCylinder(const std::shared_ptr<Player> &player, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder, const std::shared_ptr<Item> &item, Position toPos) { if (!player || !toCylinder || !item) { return RETURNVALUE_NOTPOSSIBLE; } @@ -1858,7 +1918,9 @@ ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr<Player> player, std::s } } - if (containerID == ITEM_GOLD_POUCH) { + const auto containerToStow = isTryingToStow(toPos, toCylinder); + + if (containerID == ITEM_GOLD_POUCH && !containerToStow) { if (g_configManager().getBoolean(TOGGLE_GOLD_POUCH_QUICKLOOT_ONLY)) { return RETURNVALUE_CONTAINERNOTENOUGHROOM; } @@ -1884,7 +1946,7 @@ ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr<Player> player, std::s return RETURNVALUE_NOTBOUGHTINSTORE; } - if (item->isStoreItem()) { + if (item->isStoreItem() && !containerToStow) { bool isValidMoveItem = false; auto fromHouseTile = fromCylinder->getTile(); auto house = fromHouseTile ? fromHouseTile->getHouse() : nullptr; @@ -1915,7 +1977,7 @@ ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr<Player> player, std::s if (item->getContainer() && !item->isStoreItem()) { for (const std::shared_ptr<Item> &containerItem : item->getContainer()->getItems(true)) { - if (containerItem->isStoreItem() && ((containerID != ITEM_GOLD_POUCH && containerID != ITEM_DEPOT && containerID != ITEM_STORE_INBOX) || (topParentContainer->getParent() && topParentContainer->getParent()->getContainer() && (!topParentContainer->getParent()->getContainer()->isDepotChest() || topParentContainer->getParent()->getContainer()->getID() != ITEM_STORE_INBOX)))) { + if (containerItem->isStoreItem() && !containerToStow && ((containerID != ITEM_GOLD_POUCH && containerID != ITEM_DEPOT && containerID != ITEM_STORE_INBOX) || (topParentContainer->getParent() && topParentContainer->getParent()->getContainer() && (!topParentContainer->getParent()->getContainer()->isDepotChest() || topParentContainer->getParent()->getContainer()->getID() != ITEM_STORE_INBOX)))) { return RETURNVALUE_NOTPOSSIBLE; } } @@ -1946,8 +2008,8 @@ ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr<Player> player, std::s return RETURNVALUE_NOERROR; } -ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, int32_t index, std::shared_ptr<Item> item, uint32_t count, std::shared_ptr<Item>* movedItem, uint32_t flags /*= 0*/, std::shared_ptr<Creature> actor /*=nullptr*/, std::shared_ptr<Item> tradeItem /* = nullptr*/, bool checkTile /* = true*/) { - metrics::method_latency measure(__METHOD_NAME__); +ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, int32_t index, const std::shared_ptr<Item> &item, uint32_t count, std::shared_ptr<Item>* movedItem, uint32_t flags /*= 0*/, const std::shared_ptr<Creature> &actor /*=nullptr*/, const std::shared_ptr<Item> &tradeItem /* = nullptr*/, bool checkTile /* = true*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (fromCylinder == nullptr) { g_logger().error("[{}] fromCylinder is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; @@ -1958,7 +2020,7 @@ ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std:: } if (checkTile) { - if (std::shared_ptr<Tile> fromTile = fromCylinder->getTile()) { + if (const std::shared_ptr<Tile> &fromTile = fromCylinder->getTile()) { if (fromTile && browseFields.contains(fromTile) && browseFields[fromTile].lock() == fromCylinder) { fromCylinder = fromTile; } @@ -1967,10 +2029,14 @@ ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std:: std::shared_ptr<Item> toItem = nullptr; - std::shared_ptr<Cylinder> subCylinder; + std::shared_ptr<Cylinder> subCylinder = nullptr; int floorN = 0; - while ((subCylinder = toCylinder->queryDestination(index, item, &toItem, flags)) != toCylinder) { + while ((subCylinder = toCylinder->queryDestination(index, item, toItem, flags)) != toCylinder) { + if (subCylinder == nullptr) { + break; + } + toCylinder = subCylinder; flags = 0; @@ -2178,10 +2244,10 @@ ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std:: return ret; } - if (std::shared_ptr<Player> player = actor->getPlayer()) { + if (const auto &playerActor = actor->getPlayer()) { // Refresh depot search window if necessary - if (player->isDepotSearchOpenOnItem(item->getID()) && ((fromCylinder->getItem() && fromCylinder->getItem()->isInsideDepot(true)) || (toCylinder->getItem() && toCylinder->getItem()->isInsideDepot(true)))) { - player->requestDepotSearchItem(item->getID(), item->getTier()); + if (playerActor->isDepotSearchOpenOnItem(item->getID()) && ((fromCylinder->getItem() && fromCylinder->getItem()->isInsideDepot(true)) || (toCylinder->getItem() && toCylinder->getItem()->isInsideDepot(true)))) { + playerActor->requestDepotSearchItem(item->getID(), item->getTier()); } const ItemType &it = Item::items[fromCylinder->getItem()->getID()]; @@ -2190,8 +2256,8 @@ ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std:: } // Looting analyser - if (it.isCorpse && toContainer->getTopParent() == player && item->getIsLootTrackeable()) { - player->sendLootStats(item, static_cast<uint8_t>(item->getItemCount())); + if (it.isCorpse && toContainer->getTopParent() == playerActor && item->getIsLootTrackeable()) { + playerActor->sendLootStats(item, static_cast<uint8_t>(item->getItemCount())); } } } @@ -2199,13 +2265,13 @@ ReturnValue Game::internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std:: return ret; } -ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, int32_t index /*= INDEX_WHEREEVER*/, uint32_t flags /* = 0*/, bool test /* = false*/) { +ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, const std::shared_ptr<Item> &item, int32_t index /*= INDEX_WHEREEVER*/, uint32_t flags /* = 0*/, bool test /* = false*/) { uint32_t remainderCount = 0; - return internalAddItem(std::move(toCylinder), std::move(item), index, flags, test, remainderCount); + return internalAddItem(std::move(toCylinder), item, index, flags, test, remainderCount); } -ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, int32_t index, uint32_t flags, bool test, uint32_t &remainderCount) { - metrics::method_latency measure(__METHOD_NAME__); +ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, const std::shared_ptr<Item> &item, int32_t index, uint32_t flags, bool test, uint32_t &remainderCount) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (toCylinder == nullptr) { g_logger().error("[{}] fromCylinder is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; @@ -2219,7 +2285,7 @@ ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::sha std::shared_ptr<Cylinder> destCylinder = toCylinder; std::shared_ptr<Item> toItem = nullptr; - toCylinder = toCylinder->queryDestination(index, item, &toItem, flags); + toCylinder = toCylinder->queryDestination(index, item, toItem, flags); // check if we can add this item ReturnValue ret = toCylinder->queryAdd(index, item, item->getItemCount(), flags); @@ -2291,8 +2357,9 @@ ReturnValue Game::internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::sha return RETURNVALUE_NOERROR; } -ReturnValue Game::internalRemoveItem(std::shared_ptr<Item> item, int32_t count /*= -1*/, bool test /*= false*/, uint32_t flags /*= 0*/, bool force /*= false*/) { - metrics::method_latency measure(__METHOD_NAME__); +ReturnValue Game::internalRemoveItem(const std::shared_ptr<Item> &items, int32_t count /*= -1*/, bool test /*= false*/, uint32_t flags /*= 0*/, bool force /*= false*/) { + auto item = items; + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (item == nullptr) { g_logger().debug("{} - Item is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; @@ -2302,7 +2369,7 @@ ReturnValue Game::internalRemoveItem(std::shared_ptr<Item> item, int32_t count / g_logger().debug("{} - Cylinder is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Tile> fromTile = cylinder->getTile(); + const auto &fromTile = cylinder->getTile(); if (fromTile) { if (fromTile && browseFields.contains(fromTile) && browseFields[fromTile].lock() == cylinder) { cylinder = fromTile; @@ -2342,7 +2409,7 @@ ReturnValue Game::internalRemoveItem(std::shared_ptr<Item> item, int32_t count / cylinder->postRemoveNotification(item, nullptr, index); } - std::shared_ptr<Item> quiver = cylinder->getItem(); + const auto &quiver = cylinder->getItem(); if (quiver && quiver->isQuiver() && quiver->getHoldingPlayer() && quiver->getHoldingPlayer()->getThing(CONST_SLOT_RIGHT) == quiver) { @@ -2372,8 +2439,8 @@ std::tuple<ReturnValue, uint32_t, uint32_t> Game::addItemBatch(const std::shared return std::make_tuple(ret, totalAdded, containersCreated); } - metrics::method_latency measure(__METHOD_NAME__); - const auto player = toCylinder->getPlayer(); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = toCylinder->getPlayer(); bool dropping = false; auto setupDestination = [&]() -> std::shared_ptr<Cylinder> { if (autoContainerId == 0) { @@ -2452,7 +2519,7 @@ std::tuple<ReturnValue, uint32_t, uint32_t> Game::addItemBatch(const std::shared } std::tuple<ReturnValue, uint32_t, uint32_t> Game::createItemBatch(const std::shared_ptr<Cylinder> &toCylinder, const std::vector<std::tuple<uint16_t, uint32_t, uint16_t>> &itemCounts, uint32_t flags /* = 0 */, bool dropOnMap /* = true */, uint32_t autoContainerId /* = 0 */) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); std::vector<std::shared_ptr<Item>> items; for (const auto &[itemId, count, subType] : itemCounts) { const auto &itemType = Item::items[itemId]; @@ -2485,8 +2552,8 @@ std::tuple<ReturnValue, uint32_t, uint32_t> Game::createItem(const std::shared_p return createItemBatch(toCylinder, { std::make_tuple(itemId, count, subType) }, flags, dropOnMap, autoContainerId); } -ReturnValue Game::internalPlayerAddItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, bool dropOnMap /*= true*/, Slots_t slot /*= CONST_SLOT_WHEREEVER*/) { - metrics::method_latency measure(__METHOD_NAME__); +ReturnValue Game::internalPlayerAddItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, bool dropOnMap /*= true*/, Slots_t slot /*= CONST_SLOT_WHEREEVER*/) { + metrics::method_latency measure(__METRICS_METHOD_NAME__); uint32_t remainderCount = 0; ReturnValue ret; if (slot == CONST_SLOT_WHEREEVER) { @@ -2517,8 +2584,8 @@ ReturnValue Game::internalPlayerAddItem(std::shared_ptr<Player> player, std::sha return ret; } -std::shared_ptr<Item> Game::findItemOfType(std::shared_ptr<Cylinder> cylinder, uint16_t itemId, bool depthSearch /*= true*/, int32_t subType /*= -1*/) const { - metrics::method_latency measure(__METHOD_NAME__); +std::shared_ptr<Item> Game::findItemOfType(const std::shared_ptr<Cylinder> &cylinder, uint16_t itemId, bool depthSearch /*= true*/, int32_t subType /*= -1*/) const { + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (cylinder == nullptr) { g_logger().error("[{}] Cylinder is nullptr", __FUNCTION__); return nullptr; @@ -2526,12 +2593,12 @@ std::shared_ptr<Item> Game::findItemOfType(std::shared_ptr<Cylinder> cylinder, u std::vector<std::shared_ptr<Container>> containers; for (size_t i = cylinder->getFirstIndex(), j = cylinder->getLastIndex(); i < j; ++i) { - std::shared_ptr<Thing> thing = cylinder->getThing(i); + const std::shared_ptr<Thing> &thing = cylinder->getThing(i); if (!thing) { continue; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { continue; } @@ -2541,7 +2608,7 @@ std::shared_ptr<Item> Game::findItemOfType(std::shared_ptr<Cylinder> cylinder, u } if (depthSearch) { - std::shared_ptr<Container> container = item->getContainer(); + const std::shared_ptr<Container> &container = item->getContainer(); if (container) { containers.push_back(container); } @@ -2550,13 +2617,13 @@ std::shared_ptr<Item> Game::findItemOfType(std::shared_ptr<Cylinder> cylinder, u size_t i = 0; while (i < containers.size()) { - std::shared_ptr<Container> container = containers[i++]; - for (std::shared_ptr<Item> item : container->getItemList()) { + const std::shared_ptr<Container> &container = containers[i++]; + for (const auto &item : container->getItemList()) { if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { return item; } - std::shared_ptr<Container> subContainer = item->getContainer(); + const std::shared_ptr<Container> &subContainer = item->getContainer(); if (subContainer) { containers.push_back(subContainer); } @@ -2565,7 +2632,7 @@ std::shared_ptr<Item> Game::findItemOfType(std::shared_ptr<Cylinder> cylinder, u return nullptr; } -bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint32_t flags /*= 0*/, bool useBalance /*= false*/) { +bool Game::removeMoney(const std::shared_ptr<Cylinder> &cylinder, uint64_t money, uint32_t flags /*= 0*/, bool useBalance /*= false*/) { if (cylinder == nullptr) { g_logger().error("[{}] cylinder is nullptr", __FUNCTION__); return false; @@ -2577,15 +2644,15 @@ bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint3 std::multimap<uint32_t, std::shared_ptr<Item>> moneyMap; uint64_t moneyCount = 0; for (size_t i = cylinder->getFirstIndex(), j = cylinder->getLastIndex(); i < j; ++i) { - std::shared_ptr<Thing> thing = cylinder->getThing(i); + const std::shared_ptr<Thing> &thing = cylinder->getThing(i); if (!thing) { continue; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { continue; } - std::shared_ptr<Container> container = item->getContainer(); + const std::shared_ptr<Container> &container = item->getContainer(); if (container) { containers.push_back(container); } else { @@ -2598,9 +2665,9 @@ bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint3 } size_t i = 0; while (i < containers.size()) { - std::shared_ptr<Container> container = containers[i++]; + const std::shared_ptr<Container> &container = containers[i++]; for (const std::shared_ptr<Item> &item : container->getItemList()) { - std::shared_ptr<Container> tmpContainer = item->getContainer(); + const std::shared_ptr<Container> &tmpContainer = item->getContainer(); if (tmpContainer) { containers.push_back(tmpContainer); } else { @@ -2613,7 +2680,7 @@ bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint3 } } - std::shared_ptr<Player> player = useBalance ? std::dynamic_pointer_cast<Player>(cylinder) : nullptr; + const auto &player = useBalance ? std::dynamic_pointer_cast<Player>(cylinder) : nullptr; uint64_t balance = 0; if (useBalance && player) { balance = player->getBankBalance(); @@ -2624,7 +2691,7 @@ bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint3 } for (const auto &moneyEntry : moneyMap) { - std::shared_ptr<Item> item = moneyEntry.second; + const std::shared_ptr<Item> &item = moneyEntry.second; if (moneyEntry.first < money) { internalRemoveItem(item); money -= moneyEntry.first; @@ -2647,7 +2714,7 @@ bool Game::removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint3 return true; } -void Game::addMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint32_t flags /*= 0*/) { +void Game::addMoney(const std::shared_ptr<Cylinder> &cylinder, uint64_t money, uint32_t flags /*= 0*/) { if (cylinder == nullptr) { g_logger().error("[{}] cylinder is nullptr", __FUNCTION__); return; @@ -2656,45 +2723,35 @@ void Game::addMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint32_t return; } - uint32_t crystalCoins = money / 10000; - money -= crystalCoins * 10000; - while (crystalCoins > 0) { - const uint16_t count = std::min<uint32_t>(100, crystalCoins); + auto addCoins = [&](uint16_t itemId, uint32_t count) { + while (count > 0) { + const uint16_t createCount = std::min<uint32_t>(100, count); + const std::shared_ptr<Item> &remaindItem = Item::CreateItem(itemId, createCount); - std::shared_ptr<Item> remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count); + ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); + if (ret != RETURNVALUE_NOERROR) { + internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); + } - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); + count -= createCount; } + }; - crystalCoins -= count; - } + uint32_t crystalCoins = money / 10000; + money -= crystalCoins * 10000; + addCoins(ITEM_CRYSTAL_COIN, crystalCoins); uint16_t platinumCoins = money / 100; - if (platinumCoins != 0) { - std::shared_ptr<Item> remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins); - - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - - money -= platinumCoins * 100; - } - - if (money != 0) { - std::shared_ptr<Item> remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money); + money -= platinumCoins * 100; + addCoins(ITEM_PLATINUM_COIN, platinumCoins); - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - } + if (money > 0) { + addCoins(ITEM_GOLD_COIN, money); } } std::shared_ptr<Item> Game::transformItem(std::shared_ptr<Item> item, uint16_t newId, int32_t newCount /*= -1*/) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (item->getID() == newId && (newCount == -1 || (newCount == item->getSubType() && newCount != 0))) { // chargeless item placed on map = infinite return item; } @@ -2832,7 +2889,7 @@ std::shared_ptr<Item> Game::transformItem(std::shared_ptr<Item> item, uint16_t n } ReturnValue Game::internalTeleport(const std::shared_ptr<Thing> &thing, const Position &newPos, bool pushMove /* = true*/, uint32_t flags /*= 0*/) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (thing == nullptr) { g_logger().error("[{}] thing is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; @@ -2855,18 +2912,16 @@ ReturnValue Game::internalTeleport(const std::shared_ptr<Thing> &thing, const Po return ret; } - g_dispatcher().addWalkEvent([=] { - g_game().map.moveCreature(creature, toTile, !pushMove); - }); + map.moveCreature(creature, toTile, !pushMove); return RETURNVALUE_NOERROR; - } else if (std::shared_ptr<Item> item = thing->getItem()) { + } else if (const auto &item = thing->getItem()) { return internalMoveItem(item->getParent(), toTile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr, flags); } return RETURNVALUE_NOTPOSSIBLE; } -void Game::playerQuickLootCorpse(std::shared_ptr<Player> player, std::shared_ptr<Container> corpse, const Position &position) { +void Game::playerQuickLootCorpse(const std::shared_ptr<Player> &player, const std::shared_ptr<Container> &corpse, const Position &position) { if (!player || !corpse) { return; } @@ -2878,7 +2933,7 @@ void Game::playerQuickLootCorpse(std::shared_ptr<Player> player, std::shared_ptr bool missedAnyItem = false; for (ContainerIterator it = corpse->iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; + const auto &item = *it; bool listed = player->isQuickLootListedItem(item); if ((listed && ignoreListItems) || (!listed && !ignoreListItems)) { if (item->getWorth() != 0) { @@ -3005,7 +3060,7 @@ void Game::playerQuickLootCorpse(std::shared_ptr<Player> player, std::shared_ptr player->lastQuickLootNotification = OTSYS_TIME(); } -std::shared_ptr<Container> Game::findManagedContainer(std::shared_ptr<Player> player, bool &fallbackConsumed, ObjectCategory_t category, bool isLootContainer) { +std::shared_ptr<Container> Game::findManagedContainer(const std::shared_ptr<Player> &player, bool &fallbackConsumed, ObjectCategory_t category, bool isLootContainer) { auto lootContainer = player->getManagedContainer(category, isLootContainer); if (!lootContainer && player->quickLootFallbackToMainContainer && !fallbackConsumed) { auto fallbackItem = player->getInventoryItem(CONST_SLOT_BACKPACK); @@ -3046,7 +3101,7 @@ std::shared_ptr<Container> Game::findNextAvailableContainer(ContainerIterator &c return nullptr; } -bool Game::handleFallbackLogic(std::shared_ptr<Player> player, std::shared_ptr<Container> &lootContainer, ContainerIterator &containerIterator, const bool &fallbackConsumed) { +bool Game::handleFallbackLogic(const std::shared_ptr<Player> &player, std::shared_ptr<Container> &lootContainer, ContainerIterator &containerIterator, const bool &fallbackConsumed) { if (fallbackConsumed || !player->quickLootFallbackToMainContainer) { return false; } @@ -3062,7 +3117,7 @@ bool Game::handleFallbackLogic(std::shared_ptr<Player> player, std::shared_ptr<C return true; } -ReturnValue Game::processMoveOrAddItemToLootContainer(std::shared_ptr<Item> item, std::shared_ptr<Container> lootContainer, uint32_t &remainderCount, std::shared_ptr<Player> player) { +ReturnValue Game::processMoveOrAddItemToLootContainer(const std::shared_ptr<Item> &item, const std::shared_ptr<Container> &lootContainer, uint32_t &remainderCount, const std::shared_ptr<Player> &player) { std::shared_ptr<Item> moveItem = nullptr; ReturnValue ret; if (item->getParent()) { @@ -3076,7 +3131,7 @@ ReturnValue Game::processMoveOrAddItemToLootContainer(std::shared_ptr<Item> item return ret; } -ReturnValue Game::processLootItems(std::shared_ptr<Player> player, std::shared_ptr<Container> lootContainer, std::shared_ptr<Item> item, bool &fallbackConsumed) { +ReturnValue Game::processLootItems(const std::shared_ptr<Player> &player, std::shared_ptr<Container> lootContainer, const std::shared_ptr<Item> &item, bool &fallbackConsumed) { std::shared_ptr<Container> lastSubContainer = nullptr; uint32_t remainderCount = item->getItemCount(); ContainerIterator containerIterator = lootContainer->iterator(); @@ -3098,7 +3153,7 @@ ReturnValue Game::processLootItems(std::shared_ptr<Player> player, std::shared_p return ret; } -ReturnValue Game::internalCollectManagedItems(std::shared_ptr<Player> player, std::shared_ptr<Item> item, ObjectCategory_t category /* = OBJECTCATEGORY_DEFAULT*/, bool isLootContainer /* = true*/) { +ReturnValue Game::internalCollectManagedItems(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, ObjectCategory_t category, bool isLootContainer /* = true*/) { if (!player || !item) { return RETURNVALUE_NOTPOSSIBLE; } @@ -3136,7 +3191,7 @@ ReturnValue Game::internalCollectManagedItems(std::shared_ptr<Player> player, st return processLootItems(player, lootContainer, item, fallbackConsumed); } -ReturnValue Game::collectRewardChestItems(std::shared_ptr<Player> player, uint32_t maxMoveItems /* = 0*/) { +ReturnValue Game::collectRewardChestItems(const std::shared_ptr<Player> &player, uint32_t maxMoveItems /* = 0*/) { // Check if have item on player reward chest std::shared_ptr<RewardChest> rewardChest = player->getRewardChest(); if (rewardChest->empty()) { @@ -3179,7 +3234,7 @@ ReturnValue Game::collectRewardChestItems(std::shared_ptr<Player> player, uint32 return RETURNVALUE_NOERROR; } -ObjectCategory_t Game::getObjectCategory(std::shared_ptr<Item> item) { +ObjectCategory_t Game::getObjectCategory(const std::shared_ptr<Item> &item) { ObjectCategory_t category = OBJECTCATEGORY_DEFAULT; if (!item) { return OBJECTCATEGORY_NONE; @@ -3282,7 +3337,7 @@ uint64_t Game::getItemMarketPrice(const std::map<uint16_t, uint64_t> &itemMap, b return total; } -std::shared_ptr<Item> searchForItem(std::shared_ptr<Container> container, uint16_t itemId, bool hasTier /* = false*/, uint8_t tier /* = 0*/) { +std::shared_ptr<Item> searchForItem(const std::shared_ptr<Container> &container, uint16_t itemId, bool hasTier /* = false*/, uint8_t tier /* = 0*/) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { if ((*it)->getID() == itemId && (!hasTier || (*it)->getTier() == tier)) { return *it; @@ -3319,9 +3374,8 @@ Slots_t getSlotType(const ItemType &it) { return slot; } -// Implementation of player invoked events void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = false*/, uint8_t tier /* = 0*/) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3334,12 +3388,12 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = return; } - std::shared_ptr<Item> item = player->getInventoryItem(CONST_SLOT_BACKPACK); + const auto &item = player->getInventoryItem(CONST_SLOT_BACKPACK); if (!item) { return; } - std::shared_ptr<Container> backpack = item->getContainer(); + const std::shared_ptr<Container> &backpack = item->getContainer(); if (!backpack) { return; } @@ -3352,21 +3406,25 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = const ItemType &it = Item::items[itemId]; Slots_t slot = getSlotType(it); - auto slotItem = player->getInventoryItem(slot); - auto equipItem = searchForItem(backpack, it.id, hasTier, tier); + const auto &slotItem = player->getInventoryItem(slot); + const auto &equipItem = searchForItem(backpack, it.id, hasTier, tier); ReturnValue ret = RETURNVALUE_NOERROR; + if (slotItem && slotItem->getID() == it.id && (!it.stackable || slotItem->getItemCount() == slotItem->getStackSize() || !equipItem)) { ret = internalMoveItem(slotItem->getParent(), player, CONST_SLOT_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr); g_logger().debug("Item {} was unequipped", slotItem->getName()); } else if (equipItem) { // Shield slot item const auto &rightItem = player->getInventoryItem(CONST_SLOT_RIGHT); + // Check Ammo item if (it.weaponType == WEAPON_AMMO) { if (rightItem && rightItem->isQuiver()) { ret = internalMoveItem(equipItem->getParent(), rightItem->getContainer(), 0, equipItem, equipItem->getItemCount(), nullptr); } } else { + const auto &leftItem = player->getInventoryItem(CONST_SLOT_LEFT); + const int32_t &slotPosition = equipItem->getSlotPosition(); // Checks if a two-handed item is being equipped in the left slot when the right slot is already occupied and move to backpack if ( @@ -3375,10 +3433,35 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = && rightItem && !(it.weaponType == WEAPON_DISTANCE) && !rightItem->isQuiver() + && (!leftItem || leftItem->getWeaponType() != WEAPON_DISTANCE) ) { ret = internalCollectManagedItems(player, rightItem, getObjectCategory(rightItem), false); } + // Check if trying to equip a quiver while another quiver is already equipped in the right slot + if (slot == CONST_SLOT_RIGHT && rightItem && rightItem->isQuiver() && it.isQuiver()) { + // Replace the existing quiver with the new one + ret = internalMoveItem(rightItem->getParent(), player, INDEX_WHEREEVER, rightItem, rightItem->getItemCount(), nullptr); + if (ret == RETURNVALUE_NOERROR) { + g_logger().debug("Quiver {} was unequipped to equip new quiver", rightItem->getName()); + } else { + player->sendCancelMessage(ret); + return; + } + } else { + // Check if trying to equip a shield while a two-handed weapon is equipped in the left slot + if (slot == CONST_SLOT_RIGHT && leftItem && leftItem->getSlotPosition() & SLOTP_TWO_HAND) { + // Unequip the two-handed weapon from the left slot + ret = internalMoveItem(leftItem->getParent(), player, INDEX_WHEREEVER, leftItem, leftItem->getItemCount(), nullptr); + if (ret == RETURNVALUE_NOERROR) { + g_logger().debug("Two-handed weapon {} was unequipped to equip shield", leftItem->getName()); + } else { + player->sendCancelMessage(ret); + return; + } + } + } + if (slotItem) { ret = internalMoveItem(slotItem->getParent(), player, INDEX_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr); g_logger().debug("Item {} was moved back to player", slotItem->getName()); @@ -3397,7 +3480,7 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* = } void Game::playerMove(uint32_t playerId, Direction direction) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3410,7 +3493,7 @@ void Game::playerMove(uint32_t playerId, Direction direction) { } void Game::forcePlayerMove(uint32_t playerId, Direction direction) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3422,7 +3505,7 @@ void Game::forcePlayerMove(uint32_t playerId, Direction direction) { player->startAutoWalk(std::vector<Direction> { direction }, true); } -bool Game::playerBroadcastMessage(std::shared_ptr<Player> player, const std::string &text) const { +bool Game::playerBroadcastMessage(const std::shared_ptr<Player> &player, const std::string &text) const { if (!player->hasFlag(PlayerFlags_t::CanBroadcast)) { return false; } @@ -3437,7 +3520,7 @@ bool Game::playerBroadcastMessage(std::shared_ptr<Player> player, const std::str } void Game::playerCreatePrivateChannel(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isPremium()) { return; } @@ -3451,7 +3534,7 @@ void Game::playerCreatePrivateChannel(uint32_t playerId) { } void Game::playerChannelInvite(uint32_t playerId, const std::string &name) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3474,7 +3557,7 @@ void Game::playerChannelInvite(uint32_t playerId, const std::string &name) { } void Game::playerChannelExclude(uint32_t playerId, const std::string &name) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3497,7 +3580,7 @@ void Game::playerChannelExclude(uint32_t playerId, const std::string &name) { } void Game::playerRequestChannels(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3506,7 +3589,7 @@ void Game::playerRequestChannels(uint32_t playerId) { } void Game::playerOpenChannel(uint32_t playerId, uint16_t channelId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3528,7 +3611,7 @@ void Game::playerOpenChannel(uint32_t playerId, uint16_t channelId) { } void Game::playerCloseChannel(uint32_t playerId, uint16_t channelId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3537,7 +3620,7 @@ void Game::playerCloseChannel(uint32_t playerId, uint16_t channelId) { } void Game::playerOpenPrivateChannel(uint32_t playerId, std::string &receiver) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3567,7 +3650,7 @@ void Game::playerCloseNpcChannel(uint32_t playerId) { } void Game::playerReceivePing(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3576,7 +3659,7 @@ void Game::playerReceivePing(uint32_t playerId) { } void Game::playerReceivePingBack(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3585,7 +3668,7 @@ void Game::playerReceivePingBack(uint32_t playerId) { } void Game::playerAutoWalk(uint32_t playerId, const std::vector<Direction> &listDir) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3596,7 +3679,7 @@ void Game::playerAutoWalk(uint32_t playerId, const std::vector<Direction> &listD } void Game::forcePlayerAutoWalk(uint32_t playerId, const std::vector<Direction> &listDir) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3613,7 +3696,7 @@ void Game::forcePlayerAutoWalk(uint32_t playerId, const std::vector<Direction> & } void Game::playerStopAutoWalk(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3622,8 +3705,8 @@ void Game::playerStopAutoWalk(uint32_t playerId) { } void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t fromStackPos, uint16_t fromItemId, const Position &toPos, uint8_t toStackPos, uint16_t toItemId) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3633,13 +3716,13 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f return; } - std::shared_ptr<Thing> thing = internalGetThing(player, fromPos, fromStackPos, fromItemId, STACKPOS_FIND_THING); + const std::shared_ptr<Thing> &thing = internalGetThing(player, fromPos, fromStackPos, fromItemId, STACKPOS_FIND_THING); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || !item->isMultiUse() || item->getID() != fromItemId) { player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); return; @@ -3767,8 +3850,8 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f } void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPos, uint8_t index, uint16_t itemId) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -3778,13 +3861,13 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); + const auto &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->isMultiUse() || item->getID() != itemId) { player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); return; @@ -3877,13 +3960,13 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo } void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uint8_t fromStackPos, uint32_t creatureId, uint16_t itemId) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Creature> creature = getCreatureByID(creatureId); + const std::shared_ptr<Creature> &creature = getCreatureByID(creatureId); if (!creature) { return; } @@ -3900,13 +3983,13 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin } } - std::shared_ptr<Thing> thing = internalGetThing(player, fromPos, fromStackPos, itemId, STACKPOS_FIND_THING); + const std::shared_ptr<Thing> &thing = internalGetThing(player, fromPos, fromStackPos, itemId, STACKPOS_FIND_THING); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || !item->isMultiUse() || item->getID() != itemId) { player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); return; @@ -4035,7 +4118,7 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin } void Game::playerCloseContainer(uint32_t playerId, uint8_t cid) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4045,7 +4128,7 @@ void Game::playerCloseContainer(uint32_t playerId, uint8_t cid) { } void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4072,7 +4155,7 @@ void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - parentContainer = Container::create(tile); + parentContainer = Container::createBrowseField(tile); browseFields[tile] = parentContainer; } else { parentContainer = it->second.lock(); @@ -4097,7 +4180,7 @@ void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) { } void Game::playerUpdateContainer(uint32_t playerId, uint8_t cid) { - std::shared_ptr<Player> player = getPlayerByGUID(playerId); + const auto &player = getPlayerByGUID(playerId); if (!player) { return; } @@ -4111,17 +4194,17 @@ void Game::playerUpdateContainer(uint32_t playerId, uint8_t cid) { } void Game::playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); + const auto &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || !item->isRotatable() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -4166,17 +4249,17 @@ void Game::playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stac } void Game::playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || pos.x == 0xFFFF) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || !item->isPodium() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -4230,17 +4313,17 @@ void Game::playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, } void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Position &pos, uint8_t stackPos, const uint16_t itemId, uint8_t podiumVisible, uint8_t direction) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || pos.x == 0xFFFF) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || !item->isPodium() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -4256,7 +4339,7 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos return; } - const auto tile = item->getParent() ? item->getParent()->getTile() : nullptr; + const auto &tile = item->getParent() ? item->getParent()->getTile() : nullptr; if (!tile) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -4298,7 +4381,7 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos outfit.lookAddons = 0; } - const auto mount = mounts.getMountByClientID(outfit.lookMount); + const auto mount = mounts->getMountByClientID(outfit.lookMount); if (!mount || !player->hasMount(mount) || player->isWearingSupportOutfit()) { outfit.lookMount = 0; } @@ -4364,24 +4447,35 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos } void Game::playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); + const auto &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); if (!thing) { return; } - const auto item = thing->getItem(); - const auto tile = map.getTile(item->getPosition()); + const auto &item = thing->getItem(); + if (!item) { + g_logger().error("Game::playerWrapableItem: Invalid item on position: {}", pos.toString()); + player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + const auto &tile = map.getTile(item->getPosition()); + if (!tile) { + g_logger().error("Game::playerWrapableItem: Invalid tile on position: {}", pos.toString()); + player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); + return; + } + const auto houseTile = tile->dynamic_self_cast<HouseTile>(); if (!tile->hasFlag(TILESTATE_PROTECTIONZONE) || !houseTile) { player->sendCancelMessage("You may construct this only inside a house."); return; } - const auto house = houseTile->getHouse(); + const auto &house = houseTile->getHouse(); if (!house) { player->sendCancelMessage("You may construct this only inside a house."); return; @@ -4461,7 +4555,7 @@ void Game::playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t st addMagicEffect(pos, CONST_ME_POFF); } -std::shared_ptr<Item> Game::wrapItem(std::shared_ptr<Item> item, std::shared_ptr<House> house) { +std::shared_ptr<Item> Game::wrapItem(const std::shared_ptr<Item> &item, const std::shared_ptr<House> &house) { uint16_t hiddenCharges = 0; uint16_t amount = item->getItemCount(); if (isCaskItem(item->getID())) { @@ -4477,27 +4571,27 @@ std::shared_ptr<Item> Game::wrapItem(std::shared_ptr<Item> item, std::shared_ptr newItem->setCustomAttribute("unWrapId", static_cast<int64_t>(oldItemID)); newItem->setAttribute(ItemAttribute_t::DESCRIPTION, "Unwrap it in your own house to create a <" + itemName + ">."); if (hiddenCharges > 0) { - newItem->setAttribute(DATE, hiddenCharges); + newItem->setAttribute(ItemAttribute_t::DATE, hiddenCharges); } if (amount > 0) { - newItem->setAttribute(AMOUNT, amount); + newItem->setAttribute(ItemAttribute_t::AMOUNT, amount); } newItem->startDecaying(); return newItem; } -void Game::unwrapItem(std::shared_ptr<Item> item, uint16_t unWrapId, std::shared_ptr<House> house, std::shared_ptr<Player> player) { +void Game::unwrapItem(const std::shared_ptr<Item> &item, uint16_t unWrapId, const std::shared_ptr<House> &house, const std::shared_ptr<Player> &player) { if (item->hasOwner() && !item->isOwner(player)) { player->sendCancelMessage(RETURNVALUE_ITEMISNOTYOURS); return; } - auto hiddenCharges = item->getAttribute<uint16_t>(DATE); + auto hiddenCharges = item->getAttribute<uint16_t>(ItemAttribute_t::DATE); const ItemType &newiType = Item::items.getItemType(unWrapId); if (player != nullptr && house != nullptr && newiType.isBed() && house->getMaxBeds() > -1 && house->getBedCount() >= house->getMaxBeds()) { player->sendCancelMessage("You reached the maximum beds in this house"); return; } - auto amount = item->getAttribute<uint16_t>(AMOUNT); + auto amount = item->getAttribute<uint16_t>(ItemAttribute_t::AMOUNT); if (!amount) { amount = 1; } @@ -4510,13 +4604,13 @@ void Game::unwrapItem(std::shared_ptr<Item> item, uint16_t unWrapId, std::shared newItem->setSubType(hiddenCharges); } newItem->removeCustomAttribute("unWrapId"); - newItem->removeAttribute(DESCRIPTION); + newItem->removeAttribute(ItemAttribute_t::DESCRIPTION); newItem->startDecaying(); } } void Game::playerWriteItem(uint32_t playerId, uint32_t windowTextId, const std::string &text) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4580,7 +4674,7 @@ void Game::playerWriteItem(uint32_t playerId, uint32_t windowTextId, const std:: } void Game::playerBrowseField(uint32_t playerId, const Position &pos) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4626,7 +4720,7 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - container = Container::create(tile); + container = Container::createBrowseField(tile); browseFields[tile] = container; } else { container = it->second.lock(); @@ -4644,7 +4738,7 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { } void Game::playerStowItem(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackpos, uint8_t count, bool allItems) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4654,12 +4748,12 @@ void Game::playerStowItem(uint32_t playerId, const Position &pos, uint16_t itemI return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackpos, itemId, STACKPOS_TOPDOWN_ITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackpos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || item->getItemCount() < count || item->isStoreItem()) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -4685,7 +4779,7 @@ void Game::playerStowItem(uint32_t playerId, const Position &pos, uint16_t itemI } void Game::playerStashWithdraw(uint32_t playerId, uint16_t itemId, uint32_t count, uint8_t) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4760,7 +4854,7 @@ void Game::playerStashWithdraw(uint32_t playerId, uint16_t itemId, uint32_t coun } void Game::playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_t index, uint8_t containerCategory) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4785,7 +4879,7 @@ void Game::playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_ } void Game::playerUpdateHouseWindow(uint32_t playerId, uint8_t listId, uint32_t windowTextId, const std::string &text) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4802,7 +4896,7 @@ void Game::playerUpdateHouseWindow(uint32_t playerId, uint8_t listId, uint32_t w } void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t stackPos, uint32_t tradePlayerId, uint16_t itemId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -4876,10 +4970,10 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st return; } - std::shared_ptr<Container> tradeItemContainer = tradeItem->getContainer(); + const std::shared_ptr<Container> &tradeItemContainer = tradeItem->getContainer(); if (tradeItemContainer) { for (const auto &it : tradeItems) { - std::shared_ptr<Item> item = it.first; + const auto &item = it.first; if (tradeItem == item) { player->sendTextMessage(MESSAGE_TRADE, "This item is already being traded."); return; @@ -4890,7 +4984,7 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st return; } - std::shared_ptr<Container> container = item->getContainer(); + const std::shared_ptr<Container> &container = item->getContainer(); if (container && container->isHoldingItem(tradeItem)) { player->sendTextMessage(MESSAGE_TRADE, "This item is already being traded."); return; @@ -4898,13 +4992,13 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st } } else { for (const auto &it : tradeItems) { - std::shared_ptr<Item> item = it.first; + const auto &item = it.first; if (tradeItem == item) { player->sendTextMessage(MESSAGE_TRADE, "This item is already being traded."); return; } - std::shared_ptr<Container> container = item->getContainer(); + const std::shared_ptr<Container> &container = item->getContainer(); if (container && container->isHoldingItem(tradeItem)) { player->sendTextMessage(MESSAGE_TRADE, "This item is already being traded."); return; @@ -4912,8 +5006,7 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st } } - auto tradeContainer = tradeItem->getContainer(); - if (tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100) { + if (tradeItemContainer && tradeItemContainer->getItemHoldingCount() + 1 > 100) { player->sendTextMessage(MESSAGE_TRADE, "You can not trade more than 100 items."); return; } @@ -4943,7 +5036,7 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st internalStartTrade(player, tradePartner, tradeItem); } -bool Game::internalStartTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> tradePartner, std::shared_ptr<Item> tradeItem) { +bool Game::internalStartTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &tradePartner, const std::shared_ptr<Item> &tradeItem) { if (player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == tradePartner)) { player->sendCancelMessage(RETURNVALUE_YOUAREALREADYTRADING); return false; @@ -4979,7 +5072,7 @@ bool Game::internalStartTrade(std::shared_ptr<Player> player, std::shared_ptr<Pl } void Game::playerAcceptTrade(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5080,7 +5173,7 @@ void Game::playerAcceptTrade(uint32_t playerId) { } } -std::string Game::getTradeErrorDescription(ReturnValue ret, std::shared_ptr<Item> item) { +std::string Game::getTradeErrorDescription(ReturnValue ret, const std::shared_ptr<Item> &item) { if (item) { if (ret == RETURNVALUE_NOTENOUGHCAPACITY) { std::ostringstream ss; @@ -5112,7 +5205,7 @@ std::string Game::getTradeErrorDescription(ReturnValue ret, std::shared_ptr<Item } void Game::playerLookInTrade(uint32_t playerId, bool lookAtCounterOffer, uint8_t index) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5171,7 +5264,7 @@ void Game::playerLookInTrade(uint32_t playerId, bool lookAtCounterOffer, uint8_t } void Game::playerCloseTrade(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5179,7 +5272,7 @@ void Game::playerCloseTrade(uint32_t playerId) { internalCloseTrade(player); } -void Game::internalCloseTrade(std::shared_ptr<Player> player) { +void Game::internalCloseTrade(const std::shared_ptr<Player> &player) { std::shared_ptr<Player> tradePartner = player->tradePartner; if ((tradePartner && tradePartner->getTradeState() == TRADE_TRANSFER) || player->getTradeState() == TRADE_TRANSFER) { return; @@ -5221,12 +5314,12 @@ void Game::internalCloseTrade(std::shared_ptr<Player> player) { } void Game::playerBuyItem(uint32_t playerId, uint16_t itemId, uint8_t count, uint16_t amount, bool ignoreCap /* = false*/, bool inBackpacks /* = false*/) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (amount == 0) { return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5277,12 +5370,12 @@ void Game::playerBuyItem(uint32_t playerId, uint16_t itemId, uint8_t count, uint } void Game::playerSellItem(uint32_t playerId, uint16_t itemId, uint8_t count, uint16_t amount, bool ignoreEquipped) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (amount == 0) { return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5312,7 +5405,7 @@ void Game::playerSellItem(uint32_t playerId, uint16_t itemId, uint8_t count, uin } void Game::playerCloseShop(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5321,7 +5414,7 @@ void Game::playerCloseShop(uint32_t playerId) { } void Game::playerLookInShop(uint32_t playerId, uint16_t itemId, uint8_t count) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5351,12 +5444,12 @@ void Game::playerLookInShop(uint32_t playerId, uint16_t itemId, uint8_t count) { } void Game::playerLookAt(uint32_t playerId, uint16_t itemId, const Position &pos, uint8_t stackPos) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_LOOK); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_LOOK); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -5386,12 +5479,12 @@ void Game::playerLookAt(uint32_t playerId, uint16_t itemId, const Position &pos, } void Game::playerLookInBattleList(uint32_t playerId, uint32_t creatureId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Creature> creature = getCreatureByID(creatureId); + const auto &creature = getCreatureByID(creatureId); if (!creature) { return; } @@ -5420,8 +5513,8 @@ void Game::playerLookInBattleList(uint32_t playerId, uint32_t creatureId) { g_callbacks().executeCallback(EventCallback_t::playerOnLookInBattleList, &EventCallback::playerOnLookInBattleList, player, creature, lookDistance); } -void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, std::shared_ptr<Item> defaultItem, bool lootAllCorpses, bool autoLoot) { - std::shared_ptr<Player> player = getPlayerByID(playerId); +void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, const std::shared_ptr<Item> &defaultItem, bool lootAllCorpses, bool autoLoot) { + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5471,7 +5564,7 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item std::shared_ptr<Item> item = nullptr; if (!defaultItem) { - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -5563,7 +5656,7 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item } } -void Game::playerLootAllCorpses(std::shared_ptr<Player> player, const Position &pos, bool lootAllCorpses) { +void Game::playerLootAllCorpses(const std::shared_ptr<Player> &player, const Position &pos, bool lootAllCorpses) { if (lootAllCorpses) { std::shared_ptr<Tile> tile = g_game().map.getTile(pos.x, pos.y, pos.z); if (!tile) { @@ -5613,18 +5706,18 @@ void Game::playerLootAllCorpses(std::shared_ptr<Player> player, const Position & } void Game::playerSetManagedContainer(uint32_t playerId, ObjectCategory_t category, const Position &pos, uint16_t itemId, uint8_t stackPos, bool isLootContainer) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || pos.x != 0xffff) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_USEITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_USEITEM); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - std::shared_ptr<Container> container = thing->getContainer(); + const std::shared_ptr<Container> &container = thing->getContainer(); auto allowConfig = g_configManager().getBoolean(TOGGLE_GOLD_POUCH_ALLOW_ANYTHING) || g_configManager().getBoolean(TOGGLE_GOLD_POUCH_QUICKLOOT_ONLY); if (!container || ((container->getID() == ITEM_GOLD_POUCH && category != OBJECTCATEGORY_GOLD) && !allowConfig)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); @@ -5658,7 +5751,7 @@ void Game::playerSetManagedContainer(uint32_t playerId, ObjectCategory_t categor } void Game::playerClearManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5675,7 +5768,7 @@ void Game::playerClearManagedContainer(uint32_t playerId, ObjectCategory_t categ } void Game::playerOpenManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5689,7 +5782,7 @@ void Game::playerOpenManagedContainer(uint32_t playerId, ObjectCategory_t catego } void Game::playerSetQuickLootFallback(uint32_t playerId, bool fallback) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5697,8 +5790,8 @@ void Game::playerSetQuickLootFallback(uint32_t playerId, bool fallback) { player->quickLootFallbackToMainContainer = fallback; } -void Game::playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t filter, const std::vector<uint16_t> itemIds) { - std::shared_ptr<Player> player = getPlayerByID(playerId); +void Game::playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t filter, const std::vector<uint16_t> &itemIds) { + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5711,7 +5804,7 @@ void Game::playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t fi * Depot search system ******************************************************************************/ void Game::playerRequestDepotItems(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isDepotSearchAvailable()) { return; } @@ -5726,7 +5819,7 @@ void Game::playerRequestDepotItems(uint32_t playerId) { } void Game::playerRequestCloseDepotSearch(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isDepotSearchOpen()) { return; } @@ -5736,7 +5829,7 @@ void Game::playerRequestCloseDepotSearch(uint32_t playerId) { } void Game::playerRequestDepotSearchItem(uint32_t playerId, uint16_t itemId, uint8_t tier) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isDepotSearchOpen()) { return; } @@ -5751,7 +5844,7 @@ void Game::playerRequestDepotSearchItem(uint32_t playerId, uint16_t itemId, uint } void Game::playerRequestDepotSearchRetrieve(uint32_t playerId, uint16_t itemId, uint8_t tier, uint8_t type) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isDepotSearchOpenOnItem(itemId)) { return; } @@ -5766,7 +5859,7 @@ void Game::playerRequestDepotSearchRetrieve(uint32_t playerId, uint16_t itemId, } void Game::playerRequestOpenContainerFromDepotSearch(uint32_t playerId, const Position &pos) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->isDepotSearchOpen()) { return; } @@ -5781,7 +5874,7 @@ void Game::playerRequestOpenContainerFromDepotSearch(uint32_t playerId, const Po } void Game::playerCancelAttackAndFollow(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5792,7 +5885,7 @@ void Game::playerCancelAttackAndFollow(uint32_t playerId) { } void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5803,7 +5896,7 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) { return; } - std::shared_ptr<Creature> attackCreature = getCreatureByID(creatureId); + const auto &attackCreature = getCreatureByID(creatureId); if (!attackCreature) { player->setAttackedCreature(nullptr); player->sendCancelTarget(); @@ -5823,7 +5916,7 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) { } void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5834,7 +5927,7 @@ void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) { } void Game::playerSetFightModes(uint32_t playerId, FightMode_t fightMode, bool chaseMode, bool secureMode) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5849,7 +5942,7 @@ void Game::playerRequestAddVip(uint32_t playerId, const std::string &name) { return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5885,7 +5978,7 @@ void Game::playerRequestAddVip(uint32_t playerId, const std::string &name) { } void Game::playerRequestRemoveVip(uint32_t playerId, uint32_t guid) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5894,7 +5987,7 @@ void Game::playerRequestRemoveVip(uint32_t playerId, uint32_t guid) { } void Game::playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::string &description, uint32_t icon, bool notify, std::vector<uint8_t> vipGroupsId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5903,7 +5996,7 @@ void Game::playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::str } void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t slot, bool protectionCharm) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5917,7 +6010,7 @@ void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t return; } - std::shared_ptr<Item> item = player->imbuingItem; + const auto &item = player->imbuingItem; if (!item) { return; } @@ -5932,7 +6025,7 @@ void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t } void Game::playerClearImbuement(uint32_t playerid, uint8_t slot) { - std::shared_ptr<Player> player = getPlayerByID(playerid); + const auto &player = getPlayerByID(playerid); if (!player) { return; } @@ -5941,7 +6034,7 @@ void Game::playerClearImbuement(uint32_t playerid, uint8_t slot) { return; } - std::shared_ptr<Item> item = player->imbuingItem; + const auto &item = player->imbuingItem; if (!item) { return; } @@ -5950,7 +6043,7 @@ void Game::playerClearImbuement(uint32_t playerid, uint8_t slot) { } void Game::playerCloseImbuementWindow(uint32_t playerid) { - std::shared_ptr<Player> player = getPlayerByID(playerid); + const auto &player = getPlayerByID(playerid); if (!player) { return; } @@ -5959,7 +6052,7 @@ void Game::playerCloseImbuementWindow(uint32_t playerid) { } void Game::playerTurn(uint32_t playerId, Direction dir) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5981,7 +6074,7 @@ void Game::playerRequestOutfit(uint32_t playerId) { return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -5990,7 +6083,7 @@ void Game::playerRequestOutfit(uint32_t playerId) { } void Game::playerToggleMount(uint32_t playerId, bool mount) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -6003,7 +6096,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -6016,7 +6109,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun player->setRandomMount(isMountRandomized); if (isMountRandomized && outfit.lookMount != 0 && player->hasAnyMount()) { - auto randomMount = mounts.getMountByID(player->getRandomMountId()); + auto randomMount = mounts->getMountByID(player->getRandomMountId()); outfit.lookMount = randomMount->clientId; } @@ -6026,7 +6119,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun } if (outfit.lookMount != 0) { - const auto mount = mounts.getMountByClientID(outfit.lookMount); + const auto mount = mounts->getMountByClientID(outfit.lookMount); if (!mount) { return; } @@ -6046,7 +6139,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun auto deltaSpeedChange = mount->speed; if (player->isMounted()) { - const auto prevMount = mounts.getMountByID(player->getLastMount()); + const auto prevMount = mounts->getMountByID(player->getLastMount()); if (prevMount) { deltaSpeedChange -= prevMount->speed; } @@ -6070,7 +6163,7 @@ void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit, uint8_t isMoun } void Game::playerShowQuestLog(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -6080,7 +6173,7 @@ void Game::playerShowQuestLog(uint32_t playerId) { } void Game::playerShowQuestLine(uint32_t playerId, uint16_t questId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -6090,7 +6183,7 @@ void Game::playerShowQuestLine(uint32_t playerId, uint16_t questId) { } void Game::playerSay(uint32_t playerId, uint16_t channelId, SpeakClasses type, const std::string &receiver, const std::string &text) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -6154,7 +6247,7 @@ void Game::playerSay(uint32_t playerId, uint16_t channelId, SpeakClasses type, c } } -bool Game::playerSaySpell(std::shared_ptr<Player> player, SpeakClasses type, const std::string &text) { +bool Game::playerSaySpell(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &text) { if (player->walkExhausted()) { return true; } @@ -6178,7 +6271,7 @@ bool Game::playerSaySpell(std::shared_ptr<Player> player, SpeakClasses type, con return false; } -void Game::playerWhisper(std::shared_ptr<Player> player, const std::string &text) { +void Game::playerWhisper(const std::shared_ptr<Player> &player, const std::string &text) { auto spectators = Spectators().find<Player>(player->getPosition(), false, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_X, MAP_MAX_CLIENT_VIEW_PORT_Y, MAP_MAX_CLIENT_VIEW_PORT_Y); // Send to client @@ -6198,7 +6291,7 @@ void Game::playerWhisper(std::shared_ptr<Player> player, const std::string &text } } -bool Game::playerYell(std::shared_ptr<Player> player, const std::string &text) { +bool Game::playerYell(const std::shared_ptr<Player> &player, const std::string &text) { if (player->getLevel() == 1) { player->sendTextMessage(MESSAGE_FAILURE, "You may not yell as long as you are on level 1."); return false; @@ -6218,7 +6311,7 @@ bool Game::playerYell(std::shared_ptr<Player> player, const std::string &text) { return true; } -bool Game::playerSpeakTo(std::shared_ptr<Player> player, SpeakClasses type, const std::string &receiver, const std::string &text) { +bool Game::playerSpeakTo(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &receiver, const std::string &text) { std::shared_ptr<Player> toPlayer = getPlayerByName(receiver); if (!toPlayer) { player->sendTextMessage(MESSAGE_FAILURE, "A player with this name is not online."); @@ -6244,7 +6337,7 @@ bool Game::playerSpeakTo(std::shared_ptr<Player> player, SpeakClasses type, cons return true; } -void Game::playerSpeakToNpc(std::shared_ptr<Player> player, const std::string &text) { +void Game::playerSpeakToNpc(const std::shared_ptr<Player> &player, const std::string &text) { if (player == nullptr) { g_logger().error("[Game::playerSpeakToNpc] - Player is nullptr"); return; @@ -6267,8 +6360,8 @@ void Game::playerSpeakToNpc(std::shared_ptr<Player> player, const std::string &t player->updateUIExhausted(); } -std::shared_ptr<Task> Game::createPlayerTask(uint32_t delay, std::function<void(void)> f, std::string context) const { - return Player::createPlayerTask(delay, std::move(f), std::move(context)); +std::shared_ptr<Task> Game::createPlayerTask(uint32_t delay, std::function<void(void)> f, const std::string &context) const { + return Player::createPlayerTask(delay, std::move(f), context); } //-- @@ -6280,7 +6373,7 @@ bool Game::isSightClear(const Position &fromPos, const Position &toPos, bool flo return map.isSightClear(fromPos, toPos, floorCheck); } -bool Game::internalCreatureTurn(std::shared_ptr<Creature> creature, Direction dir) { +bool Game::internalCreatureTurn(const std::shared_ptr<Creature> &creature, Direction dir) { if (creature->getDirection() == dir) { return false; } @@ -6299,7 +6392,7 @@ bool Game::internalCreatureTurn(std::shared_ptr<Creature> creature, Direction di return true; } -bool Game::internalCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, bool ghostMode, Spectators* spectatorsPtr /* = nullptr*/, const Position* pos /* = nullptr*/) { +bool Game::internalCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, bool ghostMode, Spectators* spectatorsPtr /* = nullptr*/, const Position* pos /* = nullptr*/) { if (text.empty()) { return false; } @@ -6336,10 +6429,6 @@ bool Game::internalCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses // event method for (const auto &spectator : spectators) { spectator->onCreatureSay(creature, type, text); - if (creature != spectator) { - g_events().eventCreatureOnHear(spectator, creature, text, type); - g_callbacks().executeCallback(EventCallback_t::creatureOnHear, &EventCallback::creatureOnHear, spectator, creature, text, type); - } } return true; } @@ -6372,46 +6461,47 @@ void Game::addCreatureCheck(const std::shared_ptr<Creature> &creature) { creature->creatureCheck.store(true); - if (creature->inCheckCreaturesVector.load()) { + if (creature->inCheckCreaturesVector.exchange(true)) { // already in a vector return; } - creature->inCheckCreaturesVector.store(true); - - g_dispatcher().context().tryAddEvent([this, creature] { - checkCreatureLists[uniform_random(0, EVENT_CREATURECOUNT - 1)].emplace_back(creature); + g_dispatcher().addEvent([this, index = uniform_random(0, EVENT_CREATURECOUNT - 1), creature] { + checkCreatureLists[index].emplace_back(creature); }, - "addCreatureCheck"); + "Game::addCreatureCheck"); } void Game::removeCreatureCheck(const std::shared_ptr<Creature> &creature) { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); if (creature->inCheckCreaturesVector.load()) { creature->creatureCheck.store(false); } } void Game::checkCreatures() { - metrics::method_latency measure(__METHOD_NAME__); + metrics::method_latency measure(__METRICS_METHOD_NAME__); static size_t index = 0; - std::erase_if(checkCreatureLists[index], [this](const std::shared_ptr<Creature> &creature) { - if (creature->creatureCheck && creature->isAlive()) { - creature->onThink(EVENT_CREATURE_THINK_INTERVAL); - creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL); - creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL); - return false; + std::erase_if(checkCreatureLists[index], [this](const std::weak_ptr<Creature> &weak) { + if (const auto creature = weak.lock()) { + if (creature->creatureCheck && creature->isAlive()) { + creature->onThink(EVENT_CREATURE_THINK_INTERVAL); + creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL); + creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL); + return false; + } + + creature->inCheckCreaturesVector = false; } - creature->inCheckCreaturesVector = false; return true; }); index = (index + 1) % EVENT_CREATURECOUNT; } -void Game::changeSpeed(std::shared_ptr<Creature> creature, int32_t varSpeedDelta) { +void Game::changeSpeed(const std::shared_ptr<Creature> &creature, int32_t varSpeedDelta) { int32_t varSpeed = creature->getSpeed() - creature->getBaseSpeed(); varSpeed += varSpeedDelta; @@ -6423,7 +6513,7 @@ void Game::changeSpeed(std::shared_ptr<Creature> creature, int32_t varSpeedDelta } } -void Game::setCreatureSpeed(std::shared_ptr<Creature> creature, int32_t speed) { +void Game::setCreatureSpeed(const std::shared_ptr<Creature> &creature, int32_t speed) { creature->setBaseSpeed(static_cast<uint16_t>(speed)); // Send creature speed to client @@ -6444,7 +6534,7 @@ void Game::changePlayerSpeed(const std::shared_ptr<Player> &player, int32_t varS } } -void Game::internalCreatureChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) { +void Game::internalCreatureChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) { if (!g_events().eventCreatureOnChangeOutfit(creature, outfit)) { return; } @@ -6465,28 +6555,28 @@ void Game::internalCreatureChangeOutfit(std::shared_ptr<Creature> creature, cons } } -void Game::internalCreatureChangeVisible(std::shared_ptr<Creature> creature, bool visible) { +void Game::internalCreatureChangeVisible(const std::shared_ptr<Creature> &creature, bool visible) { // Send to clients for (const auto &spectator : Spectators().find<Player>(creature->getPosition(), true)) { spectator->getPlayer()->sendCreatureChangeVisible(creature, visible); } } -void Game::changeLight(std::shared_ptr<Creature> creature) { +void Game::changeLight(const std::shared_ptr<Creature> &creature) { // Send to clients for (const auto &spectator : Spectators().find<Player>(creature->getPosition(), true)) { spectator->getPlayer()->sendCreatureLight(creature); } } -void Game::updateCreatureIcon(std::shared_ptr<Creature> creature) { +void Game::updateCreatureIcon(const std::shared_ptr<Creature> &creature) { // Send to clients for (const auto &spectator : Spectators().find<Player>(creature->getPosition(), true)) { spectator->getPlayer()->sendCreatureIcon(creature); } } -void Game::reloadCreature(std::shared_ptr<Creature> creature) { +void Game::reloadCreature(const std::shared_ptr<Creature> &creature) { if (!creature) { g_logger().error("[{}] Creature is nullptr", __FUNCTION__); return; @@ -6497,7 +6587,7 @@ void Game::reloadCreature(std::shared_ptr<Creature> creature) { } } -void Game::sendSingleSoundEffect(const Position &pos, SoundEffect_t soundId, std::shared_ptr<Creature> actor /* = nullptr*/) { +void Game::sendSingleSoundEffect(const Position &pos, SoundEffect_t soundId, const std::shared_ptr<Creature> &actor /* = nullptr*/) { if (soundId == SoundEffect_t::SILENCE) { return; } @@ -6517,7 +6607,7 @@ void Game::sendSingleSoundEffect(const Position &pos, SoundEffect_t soundId, std } } -void Game::sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundEffect, SoundEffect_t secondarySoundEffect, std::shared_ptr<Creature> actor /* = nullptr*/) { +void Game::sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundEffect, SoundEffect_t secondarySoundEffect, const std::shared_ptr<Creature> &actor /* = nullptr*/) { if (secondarySoundEffect == SoundEffect_t::SILENCE) { sendSingleSoundEffect(pos, mainSoundEffect, actor); return; @@ -6538,7 +6628,7 @@ void Game::sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundEff } } -bool Game::combatBlockHit(CombatDamage &damage, std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, bool checkDefense, bool checkArmor, bool field) { +bool Game::combatBlockHit(CombatDamage &damage, const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, bool checkDefense, bool checkArmor, bool field) { if (damage.primary.type == COMBAT_NONE && damage.secondary.type == COMBAT_NONE) { return true; } @@ -6726,7 +6816,7 @@ bool Game::combatBlockHit(CombatDamage &damage, std::shared_ptr<Creature> attack return (primaryBlockType != BLOCK_NONE) && (secondaryBlockType != BLOCK_NONE); } -void Game::combatGetTypeInfo(CombatType_t combatType, std::shared_ptr<Creature> target, TextColor_t &color, uint16_t &effect) { +void Game::combatGetTypeInfo(CombatType_t combatType, const std::shared_ptr<Creature> &target, TextColor_t &color, uint16_t &effect) { switch (combatType) { case COMBAT_PHYSICALDAMAGE: { std::shared_ptr<Item> splash = nullptr; @@ -6837,7 +6927,7 @@ void Game::combatGetTypeInfo(CombatType_t combatType, std::shared_ptr<Creature> } // Hazard combat helpers -void Game::handleHazardSystemAttack(CombatDamage &damage, std::shared_ptr<Player> player, std::shared_ptr<Monster> monster, bool isPlayerAttacker) { +void Game::handleHazardSystemAttack(CombatDamage &damage, const std::shared_ptr<Player> &player, const std::shared_ptr<Monster> &monster, bool isPlayerAttacker) { if (damage.primary.value != 0 && monster->getHazard()) { if (isPlayerAttacker) { player->parseAttackDealtHazardSystem(damage, monster); @@ -6847,7 +6937,7 @@ void Game::handleHazardSystemAttack(CombatDamage &damage, std::shared_ptr<Player } } -void Game::notifySpectators(const CreatureVector &spectators, const Position &targetPos, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster) { +void Game::notifySpectators(const CreatureVector &spectators, const Position &targetPos, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster) { if (!spectators.empty()) { for (const auto &spectator : spectators) { if (!spectator) { @@ -6876,7 +6966,7 @@ void Game::notifySpectators(const CreatureVector &spectators, const Position &ta } // Custom PvP System combat helpers -void Game::applyPvPDamage(CombatDamage &damage, std::shared_ptr<Player> attacker, std::shared_ptr<Player> target) { +void Game::applyPvPDamage(CombatDamage &damage, const std::shared_ptr<Player> &attacker, const std::shared_ptr<Player> &target) { float targetDamageReceivedMultiplier = target->vocation->pvpDamageReceivedMultiplier; float attackerDamageDealtMultiplier = attacker->vocation->pvpDamageDealtMultiplier; float levelDifferenceDamageMultiplier = this->pvpLevelDifferenceDamageMultiplier(attacker, target); @@ -6887,7 +6977,7 @@ void Game::applyPvPDamage(CombatDamage &damage, std::shared_ptr<Player> attacker damage.secondary.value = std::round(damage.secondary.value * pvpDamageMultiplier); } -float Game::pvpLevelDifferenceDamageMultiplier(std::shared_ptr<Player> attacker, std::shared_ptr<Player> target) { +float Game::pvpLevelDifferenceDamageMultiplier(const std::shared_ptr<Player> &attacker, const std::shared_ptr<Player> &target) { int32_t levelDifference = target->getLevel() - attacker->getLevel(); levelDifference = std::abs(levelDifference); bool isLowerLevel = target->getLevel() < attacker->getLevel(); @@ -6908,7 +6998,7 @@ float Game::pvpLevelDifferenceDamageMultiplier(std::shared_ptr<Player> attacker, } // Wheel of destiny combat helpers -void Game::applyWheelOfDestinyHealing(CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target) { +void Game::applyWheelOfDestinyHealing(CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, std::shared_ptr<Creature> target) { damage.primary.value += (damage.primary.value * damage.healingMultiplier) / 100.; if (attackerPlayer) { @@ -6931,7 +7021,7 @@ void Game::applyWheelOfDestinyHealing(CombatDamage &damage, std::shared_ptr<Play } } -void Game::applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target) const { +void Game::applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Creature> &target) const { // If damage is 0, it means the target is immune to the damage type, or that we missed. if (damage.primary.value == 0 && damage.secondary.value == 0) { return; @@ -6947,7 +7037,7 @@ void Game::applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, std::shared_ if (damage.secondary.value != 0) { damage.secondary.value -= attackerPlayer->wheel()->getStat(WheelStat_t::DAMAGE); } - if (damage.instantSpellName == "Twin Burst") { + if (damage.instantSpellName == "Ice Burst" || damage.instantSpellName == "Terra Burst") { int32_t damageBonus = attackerPlayer->wheel()->checkTwinBurstByTarget(target); if (damageBonus != 0) { damage.primary.value += (damage.primary.value * damageBonus) / 100.; @@ -6971,7 +7061,7 @@ void Game::applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, std::shared_ } } -int32_t Game::applyHealthChange(CombatDamage &damage, std::shared_ptr<Creature> target) const { +int32_t Game::applyHealthChange(const CombatDamage &damage, const std::shared_ptr<Creature> &target) const { int32_t targetHealth = target->getHealth(); // Wheel of destiny (Gift of Life) @@ -6988,7 +7078,7 @@ int32_t Game::applyHealthChange(CombatDamage &damage, std::shared_ptr<Creature> return targetHealth; } -bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage, bool isEvent /*= false*/) { +bool Game::combatChangeHealth(const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, CombatDamage &damage, bool isEvent /*= false*/) { using namespace std; const Position &targetPos = target->getPosition(); if (damage.primary.value > 0) { @@ -7135,7 +7225,7 @@ bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_pt int32_t distanceY = Position::getDistanceY(targetPos, attackerPos); int32_t damageX = attackerPlayer->getPerfectShotDamage(distanceX, true); int32_t damageY = attackerPlayer->getPerfectShotDamage(distanceY, true); - std::shared_ptr<Item> item = attackerPlayer->getWeapon(); + const auto &item = attackerPlayer->getWeapon(); if (item && item->getWeaponType() == WEAPON_DISTANCE) { std::shared_ptr<Item> quiver = attackerPlayer->getInventoryItem(CONST_SLOT_RIGHT); if (quiver && quiver->getWeaponType()) { @@ -7369,13 +7459,8 @@ bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_pt target->drainHealth(attacker, realDamage); if (realDamage > 0 && targetMonster) { - if (attackerPlayer && attackerPlayer->getPlayer()) { - attackerPlayer->updateImpactTracker(damage.secondary.type, damage.secondary.value); - } - if (targetMonster->israndomStepping()) { targetMonster->setIgnoreFieldDamage(true); - targetMonster->updateMapCache(); } } @@ -7410,7 +7495,7 @@ bool Game::combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_pt return true; } -void Game::updatePlayerPartyHuntAnalyzer(const CombatDamage &damage, std::shared_ptr<Player> player) const { +void Game::updatePlayerPartyHuntAnalyzer(const CombatDamage &damage, const std::shared_ptr<Player> &player) const { if (!player) { return; } @@ -7426,8 +7511,8 @@ void Game::updatePlayerPartyHuntAnalyzer(const CombatDamage &damage, std::shared } void Game::sendDamageMessageAndEffects( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, - const Position &targetPos, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Player> targetPlayer, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, + const Position &targetPos, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Player> &targetPlayer, TextMessage &message, const CreatureVector &spectators, int32_t realDamage ) { message.primary.value = damage.primary.value; @@ -7436,7 +7521,7 @@ void Game::sendDamageMessageAndEffects( sendEffects(target, damage, targetPos, message, spectators); if (shouldSendMessage(message)) { - sendMessages(std::move(attacker), target, damage, targetPos, std::move(attackerPlayer), std::move(targetPlayer), message, spectators, realDamage); + sendMessages(attacker, target, damage, targetPos, attackerPlayer, targetPlayer, message, spectators, realDamage); } } @@ -7445,8 +7530,8 @@ bool Game::shouldSendMessage(const TextMessage &message) const { } void Game::sendMessages( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, - const Position &targetPos, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Player> targetPlayer, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, + const Position &targetPos, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Player> &targetPlayer, TextMessage &message, const CreatureVector &spectators, int32_t realDamage ) const { if (attackerPlayer) { @@ -7493,8 +7578,8 @@ void Game::sendMessages( } void Game::buildMessageAsSpectator( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, - std::shared_ptr<Player> targetPlayer, TextMessage &message, std::stringstream &ss, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, + const std::shared_ptr<Player> &targetPlayer, TextMessage &message, std::stringstream &ss, const std::string &damageString, std::string &spectatorMessage ) const { if (spectatorMessage.empty()) { @@ -7526,8 +7611,8 @@ void Game::buildMessageAsSpectator( } void Game::buildMessageAsTarget( - std::shared_ptr<Creature> attacker, const CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, - std::shared_ptr<Player> targetPlayer, TextMessage &message, std::stringstream &ss, + const std::shared_ptr<Creature> &attacker, const CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, + const std::shared_ptr<Player> &targetPlayer, TextMessage &message, std::stringstream &ss, const std::string &damageString ) const { ss.str({}); @@ -7549,7 +7634,7 @@ void Game::buildMessageAsTarget( } void Game::buildMessageAsAttacker( - std::shared_ptr<Creature> target, const CombatDamage &damage, TextMessage &message, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, TextMessage &message, std::stringstream &ss, const std::string &damageString ) const { ss.str({}); @@ -7565,7 +7650,7 @@ void Game::buildMessageAsAttacker( } void Game::sendEffects( - std::shared_ptr<Creature> target, const CombatDamage &damage, const Position &targetPos, TextMessage &message, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, const Position &targetPos, TextMessage &message, const CreatureVector &spectators ) { uint16_t hitEffect; @@ -7585,7 +7670,7 @@ void Game::sendEffects( } void Game::applyCharmRune( - std::shared_ptr<Monster> targetMonster, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target, const int32_t &realDamage + const std::shared_ptr<Monster> &targetMonster, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Creature> &target, const int32_t &realDamage ) const { if (!targetMonster || !attackerPlayer) { return; @@ -7596,14 +7681,14 @@ void Game::applyCharmRune( int8_t chance = charm->id == CHARM_CRIPPLE ? charm->chance : charm->chance + attackerPlayer->getCharmChanceModifier(); g_logger().debug("charm chance: {}, base: {}, bonus: {}", chance, charm->chance, attackerPlayer->getCharmChanceModifier()); if (charm->type == CHARM_OFFENSIVE && (chance >= normal_random(0, 100))) { - g_iobestiary().parseCharmCombat(charm, attackerPlayer, std::move(target), realDamage); + g_iobestiary().parseCharmCombat(charm, attackerPlayer, target, realDamage); } } } // Mana leech void Game::applyManaLeech( - std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster, std::shared_ptr<Creature> target, const CombatDamage &damage, const int32_t &realDamage + const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster, const std::shared_ptr<Creature> &target, const CombatDamage &damage, const int32_t &realDamage ) const { // Wheel of destiny bonus - mana leech chance and amount auto wheelLeechChance = attackerPlayer->wheel()->checkDrainBodyLeech(target, SKILL_MANA_LEECH_CHANCE); @@ -7636,7 +7721,7 @@ void Game::applyManaLeech( // Life leech void Game::applyLifeLeech( - std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster, std::shared_ptr<Creature> target, const CombatDamage &damage, const int32_t &realDamage + const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster, const std::shared_ptr<Creature> &target, const CombatDamage &damage, const int32_t &realDamage ) const { // Wheel of destiny bonus - life leech chance and amount auto wheelLeechChance = attackerPlayer->wheel()->checkDrainBodyLeech(target, SKILL_LIFE_LEECH_CHANCE); @@ -7670,7 +7755,7 @@ int32_t Game::calculateLeechAmount(const int32_t &realDamage, const uint16_t &sk return std::clamp<int32_t>(static_cast<int32_t>(std::lround(intermediateResult)), 0, realDamage); } -bool Game::combatChangeMana(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) { +bool Game::combatChangeMana(const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, CombatDamage &damage) { const Position &targetPos = target->getPosition(); auto manaChange = damage.primary.value + damage.secondary.value; if (manaChange > 0) { @@ -7869,12 +7954,12 @@ bool Game::combatChangeMana(std::shared_ptr<Creature> attacker, std::shared_ptr< return true; } -void Game::addCreatureHealth(std::shared_ptr<Creature> target) { +void Game::addCreatureHealth(const std::shared_ptr<Creature> &target) { auto spectators = Spectators().find<Player>(target->getPosition(), true); addCreatureHealth(spectators.data(), target); } -void Game::addCreatureHealth(const CreatureVector &spectators, std::shared_ptr<Creature> target) { +void Game::addCreatureHealth(const CreatureVector &spectators, const std::shared_ptr<Creature> &target) { uint8_t healthPercent = std::ceil((static_cast<double>(target->getHealth()) / std::max<int32_t>(target->getMaxHealth(), 1)) * 100); if (const auto &targetPlayer = target->getPlayer()) { if (const auto &party = targetPlayer->getParty()) { @@ -7894,14 +7979,14 @@ void Game::addCreatureHealth(const CreatureVector &spectators, std::shared_ptr<C } } -void Game::addPlayerMana(std::shared_ptr<Player> target) { +void Game::addPlayerMana(const std::shared_ptr<Player> &target) { if (const auto &party = target->getParty()) { uint8_t manaPercent = std::ceil((static_cast<double>(target->getMana()) / std::max<int32_t>(target->getMaxMana(), 1)) * 100); party->updatePlayerMana(target, manaPercent); } } -void Game::addPlayerVocation(std::shared_ptr<Player> target) { +void Game::addPlayerVocation(const std::shared_ptr<Player> &target) { if (const auto &party = target->getParty()) { party->updatePlayerVocation(target); } @@ -7950,7 +8035,7 @@ void Game::addDistanceEffect(const CreatureVector &spectators, const Position &f } } -void Game::checkImbuements() { +void Game::checkImbuements() const { for (const auto &[mapPlayerId, mapPlayer] : getPlayers()) { if (!mapPlayer) { continue; @@ -8021,6 +8106,22 @@ void Game::checkLight() { } } +ItemClassification* Game::getItemsClassification(uint8_t id, bool create) { + auto it = std::ranges::find_if(itemsClassifications, [id](ItemClassification* classification) { + return classification->id == id; + }); + + if (it != itemsClassifications.end()) { + return *it; + } else if (create) { + auto itemClassification = new ItemClassification(id); + addItemsClassification(itemClassification); + return itemClassification; + } + + return nullptr; +} + LightInfo Game::getWorldLightInfo() const { return { lightLevel, 0xD7 }; } @@ -8059,7 +8160,7 @@ void Game::shutdown() { g_logger().info("Done!"); } -void Game::addBestiaryList(uint16_t raceid, std::string name) { +void Game::addBestiaryList(uint16_t raceid, const std::string &name) { auto it = BestiaryList.find(raceid); if (it != BestiaryList.end()) { return; @@ -8077,7 +8178,7 @@ void Game::broadcastMessage(const std::string &text, MessageClasses type) const } } -void Game::updateCreatureWalkthrough(std::shared_ptr<Creature> creature) { +void Game::updateCreatureWalkthrough(const std::shared_ptr<Creature> &creature) { // Send to clients for (const auto &spectator : Spectators().find<Player>(creature->getPosition(), true)) { const auto &tmpPlayer = spectator->getPlayer(); @@ -8085,7 +8186,7 @@ void Game::updateCreatureWalkthrough(std::shared_ptr<Creature> creature) { } } -void Game::updateCreatureSkull(std::shared_ptr<Creature> creature) { +void Game::updateCreatureSkull(const std::shared_ptr<Creature> &creature) const { if (getWorldType() != WORLD_TYPE_PVP) { return; } @@ -8095,13 +8196,13 @@ void Game::updateCreatureSkull(std::shared_ptr<Creature> creature) { } } -void Game::updatePlayerShield(std::shared_ptr<Player> player) { +void Game::updatePlayerShield(const std::shared_ptr<Player> &player) { for (const auto &spectator : Spectators().find<Player>(player->getPosition(), true)) { spectator->getPlayer()->sendCreatureShield(player); } } -void Game::updateCreatureType(std::shared_ptr<Creature> creature) { +void Game::updateCreatureType(const std::shared_ptr<Creature> &creature) { if (!creature) { return; } @@ -8173,8 +8274,8 @@ void Game::checkPlayersRecord() { uint32_t previousRecord = playersRecord; playersRecord = playersOnline; - for (auto &[key, it] : g_globalEvents().getEventMap(GLOBALEVENT_RECORD)) { - it->executeRecord(playersRecord, previousRecord); + for (const auto &[key, globalEvent] : g_globalEvents().getEventMap(GLOBALEVENT_RECORD)) { + globalEvent->executeRecord(playersRecord, previousRecord); } updatePlayersRecord(); } @@ -8205,7 +8306,7 @@ void Game::playerInviteToParty(uint32_t playerId, uint32_t invitedId) { return; } - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8232,7 +8333,7 @@ void Game::playerInviteToParty(uint32_t playerId, uint32_t invitedId) { party->invitePlayer(invitedPlayer); } -void Game::updatePlayerHelpers(std::shared_ptr<Player> player) { +void Game::updatePlayerHelpers(const std::shared_ptr<Player> &player) { if (!player) { return; } @@ -8244,7 +8345,7 @@ void Game::updatePlayerHelpers(std::shared_ptr<Player> player) { } void Game::playerJoinParty(uint32_t playerId, uint32_t leaderId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8268,7 +8369,7 @@ void Game::playerJoinParty(uint32_t playerId, uint32_t leaderId) { } void Game::playerRevokePartyInvitation(uint32_t playerId, uint32_t invitedId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8287,7 +8388,7 @@ void Game::playerRevokePartyInvitation(uint32_t playerId, uint32_t invitedId) { } void Game::playerPassPartyLeadership(uint32_t playerId, uint32_t newLeaderId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8306,7 +8407,7 @@ void Game::playerPassPartyLeadership(uint32_t playerId, uint32_t newLeaderId) { } void Game::playerLeaveParty(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8321,7 +8422,7 @@ void Game::playerLeaveParty(uint32_t playerId) { } void Game::playerEnableSharedPartyExperience(uint32_t playerId, bool sharedExpActive) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8336,7 +8437,7 @@ void Game::playerEnableSharedPartyExperience(uint32_t playerId, bool sharedExpAc } void Game::sendGuildMotd(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8348,7 +8449,7 @@ void Game::sendGuildMotd(uint32_t playerId) { } void Game::kickPlayer(uint32_t playerId, bool displayEffect) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8356,7 +8457,7 @@ void Game::kickPlayer(uint32_t playerId, bool displayEffect) { player->removePlayer(displayEffect); } -void Game::playerFriendSystemAction(std::shared_ptr<Player> player, uint8_t type, uint8_t titleId) { +void Game::playerFriendSystemAction(const std::shared_ptr<Player> &player, uint8_t type, uint8_t titleId) { if (type == 0x0E) { player->title()->setCurrentTitle(titleId); player->sendCyclopediaCharacterBaseInformation(); @@ -8365,7 +8466,7 @@ void Game::playerFriendSystemAction(std::shared_ptr<Player> player, uint8_t type } } -void Game::playerCyclopediaCharacterInfo(std::shared_ptr<Player> player, uint32_t characterID, CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage, uint16_t page) { +void Game::playerCyclopediaCharacterInfo(const std::shared_ptr<Player> &player, uint32_t characterID, CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage, uint16_t page) { uint32_t playerGUID = player->getGUID(); if (characterID != playerGUID) { // For now allow viewing only our character since we don't have tournaments supported @@ -8478,8 +8579,8 @@ std::string Game::generateVocationConditionHighscore(uint32_t vocation) { return queryPart.str(); } -void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage) { - std::shared_ptr<Player> player = g_game().getPlayerByID(playerID); +void Game::processHighscoreResults(const DBResult_ptr &result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage) { + const auto &player = g_game().getPlayerByID(playerID); if (!player) { return; } @@ -8491,8 +8592,8 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8 return; } - uint16_t page = result->getNumber<uint16_t>("page"); - uint32_t pages = result->getNumber<uint32_t>("entries"); + auto page = result->getNumber<uint16_t>("page"); + auto pages = result->getNumber<uint32_t>("entries"); pages += entriesPerPage - 1; pages /= entriesPerPage; @@ -8516,7 +8617,7 @@ void Game::processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8 do { const auto &voc = g_vocations().getVocation(result->getNumber<uint16_t>("vocation")); uint8_t characterVocation = voc ? voc->getClientId() : 0; - std::string loyaltyTitle = ""; // todo get loyalty title from player + std::string loyaltyTitle; // todo get loyalty title from player characters.emplace_back(std::move(result->getString("name")), result->getNumber<uint64_t>("points"), result->getNumber<uint32_t>("id"), result->getNumber<uint32_t>("rank"), result->getNumber<uint16_t>("level"), characterVocation, loyaltyTitle); } while (result->next()); } @@ -8567,7 +8668,7 @@ std::string Game::generateHighscoreOrGetCachedQueryForOurRank(const std::string return newQuery; } -void Game::playerHighscores(std::shared_ptr<Player> player, HighscoreType_t type, uint8_t category, uint32_t vocation, const std::string &, uint16_t page, uint8_t entriesPerPage) { +void Game::playerHighscores(const std::shared_ptr<Player> &player, HighscoreType_t type, uint8_t category, uint32_t vocation, const std::string &, uint16_t page, uint8_t entriesPerPage) { if (player->hasAsyncOngoingTask(PlayerAsyncTask_Highscore)) { return; } @@ -8582,8 +8683,8 @@ void Game::playerHighscores(std::shared_ptr<Player> player, HighscoreType_t type } uint32_t playerID = player->getID(); - std::function<void(DBResult_ptr, bool)> callback = [this, playerID, category, vocation, entriesPerPage](DBResult_ptr result, bool) { - processHighscoreResults(std::move(result), playerID, category, vocation, entriesPerPage); + std::function<void(DBResult_ptr, bool)> callback = [this, playerID, category, vocation, entriesPerPage](const DBResult_ptr &result, bool) { + processHighscoreResults(result, playerID, category, vocation, entriesPerPage); }; g_databaseTasks().store(query, callback); @@ -8617,7 +8718,7 @@ std::string Game::getSkillNameById(uint8_t &skill) { } void Game::playerReportRuleViolationReport(uint32_t playerId, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8627,7 +8728,7 @@ void Game::playerReportRuleViolationReport(uint32_t playerId, const std::string } void Game::playerReportBug(uint32_t playerId, const std::string &message, const Position &position, uint8_t category) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8637,7 +8738,7 @@ void Game::playerReportBug(uint32_t playerId, const std::string &message, const } void Game::playerDebugAssert(uint32_t playerId, const std::string &assertLine, const std::string &date, const std::string &description, const std::string &comment) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8652,7 +8753,7 @@ void Game::playerDebugAssert(uint32_t playerId, const std::string &assertLine, c } void Game::playerPreyAction(uint32_t playerId, uint8_t slot, uint8_t action, uint8_t option, int8_t index, uint16_t raceId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8661,7 +8762,7 @@ void Game::playerPreyAction(uint32_t playerId, uint8_t slot, uint8_t action, uin } void Game::playerTaskHuntingAction(uint32_t playerId, uint8_t slot, uint8_t action, bool upgrade, uint16_t raceId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8706,7 +8807,7 @@ void Game::playerNpcGreet(uint32_t playerId, uint32_t npcId) { } void Game::playerLeaveMarket(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8715,7 +8816,7 @@ void Game::playerLeaveMarket(uint32_t playerId) { } void Game::playerBrowseMarket(uint32_t playerId, uint16_t itemId, uint8_t tier) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8740,7 +8841,7 @@ void Game::playerBrowseMarket(uint32_t playerId, uint16_t itemId, uint8_t tier) } void Game::playerBrowseMarketOwnOffers(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8755,7 +8856,7 @@ void Game::playerBrowseMarketOwnOffers(uint32_t playerId) { } void Game::playerBrowseMarketOwnHistory(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -8841,7 +8942,7 @@ namespace { } } // namespace -bool checkCanInitCreateMarketOffer(std::shared_ptr<Player> player, uint8_t type, const ItemType &it, uint16_t amount, uint64_t price, std::ostringstream &offerStatus) { +bool checkCanInitCreateMarketOffer(const std::shared_ptr<Player> &player, uint8_t type, const ItemType &it, uint16_t amount, uint64_t price, std::ostringstream &offerStatus) { if (!player) { offerStatus << "Failed to load player"; return false; @@ -8907,7 +9008,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite // Initialize variables // Before creating the offer we will compare it with the RETURN VALUE ERROR std::ostringstream offerStatus; - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); const ItemType &it = Item::items[itemId]; // Make sure everything is ok before the create market offer starts @@ -8926,14 +9027,14 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite return; } - std::shared_ptr<DepotLocker> depotLocker = player->getDepotLocker(player->getLastDepotId()); + const std::shared_ptr<DepotLocker> &depotLocker = player->getDepotLocker(player->getLastDepotId()); if (depotLocker == nullptr) { offerStatus << "Depot locker is nullptr for player " << player->getName(); return; } if (it.id == ITEM_STORE_COIN) { - auto [transferableCoins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [transferableCoins, result] = player->getAccount()->getCoins(CoinType::Transferable); if (amount > transferableCoins) { offerStatus << "Amount is greater than coins for player " << player->getName(); @@ -8941,7 +9042,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite } // Do not register a transaction for coins creating an offer - player->getAccount()->removeCoins(enumToValue(CoinType::Transferable), static_cast<uint32_t>(amount), ""); + player->getAccount()->removeCoins(CoinType::Transferable, static_cast<uint32_t>(amount), ""); } else { if (!removeOfferItems(player, depotLocker, it, amount, tier, offerStatus)) { g_logger().error("[{}] failed to remove item with id {}, from player {}, errorcode: {}", __FUNCTION__, it.id, player->getName(), offerStatus.str()); @@ -8990,7 +9091,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite } void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->getAccount()) { return; } @@ -9009,6 +9110,7 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 return; } + const auto &playerInbox = player->getInbox(); if (offer.type == MARKETACTION_BUY) { player->setBankBalance(player->getBankBalance() + offer.price * offer.amount); g_metrics().addCounter("balance_decrease", offer.price * offer.amount, { { "player", player->getName() }, { "context", "market_purchase" } }); @@ -9022,13 +9124,14 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 if (it.id == ITEM_STORE_COIN) { // Do not register a transaction for coins upon cancellation - player->getAccount()->addCoins(enumToValue(CoinType::Transferable), offer.amount, ""); + player->getAccount()->addCoins(CoinType::Transferable, offer.amount, ""); } else if (it.stackable) { uint16_t tmpAmount = offer.amount; + while (tmpAmount > 0) { int32_t stackCount = std::min<int32_t>(it.stackSize, tmpAmount); - std::shared_ptr<Item> item = Item::CreateItem(it.id, stackCount); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(it.id, stackCount); + if (internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { break; } @@ -9047,8 +9150,8 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } for (uint16_t i = 0; i < offer.amount; ++i) { - std::shared_ptr<Item> item = Item::CreateItem(it.id, subType); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(it.id, subType); + if (internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { break; } @@ -9073,7 +9176,7 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter, uint16_t amount) { std::ostringstream offerStatus; - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || !player->getAccount()) { offerStatus << "Failed to load player"; return; @@ -9106,37 +9209,43 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 return; } + const auto &playerInbox = player->getInbox(); + uint64_t totalPrice = offer.price * amount; // The player has an offer to by something and someone is going to sell to item type // so the market action is 'buy' as who created the offer is buying. if (offer.type == MARKETACTION_BUY) { - std::shared_ptr<DepotLocker> depotLocker = player->getDepotLocker(player->getLastDepotId()); + const std::shared_ptr<DepotLocker> &depotLocker = player->getDepotLocker(player->getLastDepotId()); if (depotLocker == nullptr) { offerStatus << "Depot locker is nullptr"; return; } - std::shared_ptr<Player> buyerPlayer = getPlayerByGUID(offer.playerId, true); + const std::shared_ptr<Player> &buyerPlayer = getPlayerByGUID(offer.playerId, true); if (!buyerPlayer) { offerStatus << "Failed to load buyer player " << player->getName(); return; } - if (!buyerPlayer->getAccount()) { + const auto &buyerPlayerAccount = buyerPlayer->getAccount(); + if (!buyerPlayerAccount) { player->sendTextMessage(MESSAGE_MARKET, "Cannot accept offer."); return; } - if (player == buyerPlayer || player->getAccount() == buyerPlayer->getAccount()) { + const auto &playerAccount = player->getAccount(); + if (player == buyerPlayer || playerAccount == buyerPlayerAccount) { player->sendTextMessage(MESSAGE_MARKET, "You cannot accept your own offer."); return; } + const auto &buyerPlayerInbox = buyerPlayer->getInbox(); + if (it.id == ITEM_STORE_COIN) { - auto [transferableCoins, error] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [transferableCoins, error] = playerAccount->getCoins(CoinType::Transferable); - if (error != enumToValue(AccountErrors_t::Ok)) { + if (error != AccountErrors_t::Ok) { offerStatus << "Failed to load transferable coins for player " << player->getName(); return; } @@ -9146,8 +9255,8 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 return; } - player->getAccount()->removeCoins( - enumToValue(CoinType::Transferable), + playerAccount->removeCoins( + CoinType::Transferable, amount, "Sold on Market" ); @@ -9175,13 +9284,13 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 g_metrics().addCounter("balance_increase", totalPrice, { { "player", player->getName() }, { "context", "market_sale" } }); if (it.id == ITEM_STORE_COIN) { - buyerPlayer->getAccount()->addCoins(enumToValue(CoinType::Transferable), amount, "Purchased on Market"); + buyerPlayer->getAccount()->addCoins(CoinType::Transferable, amount, "Purchased on Market"); } else if (it.stackable) { uint16_t tmpAmount = amount; while (tmpAmount > 0) { uint16_t stackCount = std::min<uint16_t>(it.stackSize, tmpAmount); - std::shared_ptr<Item> item = Item::CreateItem(it.id, stackCount); - if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(it.id, stackCount); + if (internalAddItem(buyerPlayerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { offerStatus << "Failed to add player inbox stackable item for buy offer for player " << player->getName(); break; @@ -9202,8 +9311,8 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } for (uint16_t i = 0; i < amount; ++i) { - std::shared_ptr<Item> item = Item::CreateItem(it.id, subType); - if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(it.id, subType); + if (internalAddItem(buyerPlayerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { offerStatus << "Failed to add player inbox item for buy offer for player " << player->getName(); break; @@ -9246,15 +9355,15 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 g_metrics().addCounter("balance_decrease", totalPrice, { { "player", player->getName() }, { "context", "market_purchase" } }); if (it.id == ITEM_STORE_COIN) { - player->getAccount()->addCoins(enumToValue(CoinType::Transferable), amount, "Purchased on Market"); + player->getAccount()->addCoins(CoinType::Transferable, amount, "Purchased on Market"); } else if (it.stackable) { uint16_t tmpAmount = amount; while (tmpAmount > 0) { uint16_t stackCount = std::min<uint16_t>(it.stackSize, tmpAmount); - std::shared_ptr<Item> item = Item::CreateItem(it.id, stackCount); + const auto &item = Item::CreateItem(it.id, stackCount); if ( // Init-statement - auto ret = internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT); + auto ret = internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT); // Condition ret != RETURNVALUE_NOERROR ) { @@ -9279,10 +9388,10 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } for (uint16_t i = 0; i < amount; ++i) { - std::shared_ptr<Item> item = Item::CreateItem(it.id, subType); + const auto &item = Item::CreateItem(it.id, subType); if ( // Init-statement - auto ret = internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT); + auto ret = internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT); // Condition ret != RETURNVALUE_NOERROR ) { @@ -9300,9 +9409,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 sellerPlayer->setBankBalance(sellerPlayer->getBankBalance() + totalPrice); g_metrics().addCounter("balance_increase", totalPrice, { { "player", sellerPlayer->getName() }, { "context", "market_sale" } }); if (it.id == ITEM_STORE_COIN) { - const auto &tranferable = enumToValue(CoinType::Transferable); - const auto &removeCoin = enumToValue(CoinTransactionType::Remove); - sellerPlayer->getAccount()->registerCoinTransaction(removeCoin, tranferable, amount, "Sold on Market"); + sellerPlayer->getAccount()->registerCoinTransaction(CoinTransactionType::Remove, CoinType::Transferable, amount, "Sold on Market"); } if (it.id != ITEM_STORE_COIN) { @@ -9345,7 +9452,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string &buffer) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9356,7 +9463,7 @@ void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const st } void Game::forceRemoveCondition(uint32_t creatureId, ConditionType_t conditionType, ConditionId_t conditionId) { - std::shared_ptr<Creature> creature = getCreatureByID(creatureId); + const auto &creature = getCreatureByID(creatureId); if (!creature) { return; } @@ -9364,7 +9471,7 @@ void Game::forceRemoveCondition(uint32_t creatureId, ConditionType_t conditionTy creature->removeCondition(conditionType, conditionId, true); } -void Game::sendOfflineTrainingDialog(std::shared_ptr<Player> player) { +void Game::sendOfflineTrainingDialog(const std::shared_ptr<Player> &player) { if (!player) { return; } @@ -9375,7 +9482,7 @@ void Game::sendOfflineTrainingDialog(std::shared_ptr<Player> player) { } void Game::playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, uint8_t button, uint8_t choice) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9409,8 +9516,8 @@ void Game::playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, ui } void Game::playerForgeFuseItems(uint32_t playerId, ForgeAction_t actionType, uint16_t firstItemId, uint8_t tier, uint16_t secondItemId, bool usedCore, bool reduceTierLoss, bool convergence) { - metrics::method_latency measure(__METHOD_NAME__); - std::shared_ptr<Player> player = getPlayerByID(playerId); + metrics::method_latency measure(__METRICS_METHOD_NAME__); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9437,7 +9544,7 @@ void Game::playerForgeFuseItems(uint32_t playerId, ForgeAction_t actionType, uin } void Game::playerForgeTransferItemTier(uint32_t playerId, ForgeAction_t actionType, uint16_t donorItemId, uint8_t tier, uint16_t receiveItemId, bool convergence) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9452,7 +9559,7 @@ void Game::playerForgeTransferItemTier(uint32_t playerId, ForgeAction_t actionTy } void Game::playerForgeResourceConversion(uint32_t playerId, ForgeAction_t actionType) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9467,7 +9574,7 @@ void Game::playerForgeResourceConversion(uint32_t playerId, ForgeAction_t action } void Game::playerBrowseForgeHistory(uint32_t playerId, uint8_t page) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9482,7 +9589,7 @@ void Game::playerBrowseForgeHistory(uint32_t playerId, uint8_t page) { } void Game::playerBosstiarySlot(uint32_t playerId, uint8_t slotId, uint32_t selectedBossId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9509,23 +9616,23 @@ void Game::playerBosstiarySlot(uint32_t playerId, uint8_t slotId, uint32_t selec } void Game::playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, const Position &pos, uint8_t stackPos, const uint16_t itemId, uint8_t direction, const std::pair<uint8_t, uint8_t> &podiumAndMonsterVisible) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || pos.x == 0xFFFF) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || !item->isPodium() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - const auto tile = item->getParent() ? item->getParent()->getTile() : nullptr; + const auto &tile = item->getParent() ? item->getParent()->getTile() : nullptr; if (!tile) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -9619,17 +9726,17 @@ void Game::playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, con } void Game::playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); + const std::shared_ptr<Thing> &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_TOPDOWN_ITEM); if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != itemId || item->hasAttribute(ItemAttribute_t::UNIQUEID)) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -9709,7 +9816,7 @@ void Game::playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t st } void Game::playerRequestInventoryImbuements(uint32_t playerId, bool isTrackerOpen) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player || player->isRemoved()) { return; } @@ -9721,7 +9828,7 @@ void Game::playerRequestInventoryImbuements(uint32_t playerId, bool isTrackerOpe std::map<Slots_t, std::shared_ptr<Item>> itemsWithImbueSlotMap; for (uint8_t inventorySlot = CONST_SLOT_FIRST; inventorySlot <= CONST_SLOT_LAST; ++inventorySlot) { - auto item = player->getInventoryItem(static_cast<Slots_t>(inventorySlot)); + const auto &item = player->getInventoryItem(static_cast<Slots_t>(inventorySlot)); if (!item) { continue; } @@ -9741,7 +9848,7 @@ void Game::playerRequestInventoryImbuements(uint32_t playerId, bool isTrackerOpe } void Game::playerOpenWheel(uint32_t playerId, uint32_t ownerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9761,12 +9868,12 @@ void Game::playerOpenWheel(uint32_t playerId, uint32_t ownerId) { } void Game::playerSaveWheel(uint32_t playerId, NetworkMessage &msg) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - if (player->isUIExhausted()) { + if (player->isUIExhausted(1000)) { player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); return; } @@ -9776,7 +9883,7 @@ void Game::playerSaveWheel(uint32_t playerId, NetworkMessage &msg) { } void Game::playerWheelGemAction(uint32_t playerId, NetworkMessage &msg) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9818,7 +9925,7 @@ void Game::playerWheelGemAction(uint32_t playerId, NetworkMessage &msg) { ********************/ void Game::updatePlayerSaleItems(uint32_t playerId) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } @@ -9828,33 +9935,33 @@ void Game::updatePlayerSaleItems(uint32_t playerId) { player->setScheduledSaleUpdate(false); } -void Game::addPlayer(std::shared_ptr<Player> player) { +void Game::addPlayer(const std::shared_ptr<Player> &player) { const std::string &lowercase_name = asLowerCaseString(player->getName()); mappedPlayerNames[lowercase_name] = player; wildcardTree->insert(lowercase_name); players[player->getID()] = player; } -void Game::removePlayer(std::shared_ptr<Player> player) { +void Game::removePlayer(const std::shared_ptr<Player> &player) { const std::string &lowercase_name = asLowerCaseString(player->getName()); mappedPlayerNames.erase(lowercase_name); wildcardTree->remove(lowercase_name); players.erase(player->getID()); } -void Game::addNpc(std::shared_ptr<Npc> npc) { +void Game::addNpc(const std::shared_ptr<Npc> &npc) { npcs[npc->getID()] = npc; } -void Game::removeNpc(std::shared_ptr<Npc> npc) { +void Game::removeNpc(const std::shared_ptr<Npc> &npc) { npcs.erase(npc->getID()); } -void Game::addMonster(std::shared_ptr<Monster> monster) { +void Game::addMonster(const std::shared_ptr<Monster> &monster) { monsters[monster->getID()] = monster; } -void Game::removeMonster(std::shared_ptr<Monster> monster) { +void Game::removeMonster(const std::shared_ptr<Monster> &monster) { monsters.erase(monster->getID()); } @@ -9881,7 +9988,7 @@ std::shared_ptr<Guild> Game::getGuildByName(const std::string &name, bool allowO return it->second; } -void Game::addGuild(const std::shared_ptr<Guild> guild) { +void Game::addGuild(const std::shared_ptr<Guild> &guild) { if (!guild) { return; } @@ -9898,7 +10005,7 @@ void Game::removeGuild(uint32_t guildId) { void Game::internalRemoveItems(const std::vector<std::shared_ptr<Item>> &itemVector, uint32_t amount, bool stackable) { if (stackable) { - for (const std::shared_ptr<Item> &item : itemVector) { + for (const auto &item : itemVector) { if (item->getItemCount() > amount) { internalRemoveItem(item, amount); break; @@ -9908,7 +10015,7 @@ void Game::internalRemoveItems(const std::vector<std::shared_ptr<Item>> &itemVec } } } else { - for (const std::shared_ptr<Item> &item : itemVector) { + for (const auto &item : itemVector) { internalRemoveItem(item); } } @@ -9958,7 +10065,7 @@ void Game::removeUniqueItem(uint16_t uniqueId) { bool Game::hasEffect(uint16_t effectId) { for (uint16_t i = CONST_ME_NONE; i < CONST_ME_LAST; i++) { - MagicEffectClasses effect = static_cast<MagicEffectClasses>(i); + auto effect = static_cast<MagicEffectClasses>(i); if (effect == effectId) { return true; } @@ -9968,7 +10075,7 @@ bool Game::hasEffect(uint16_t effectId) { bool Game::hasDistanceEffect(uint16_t effectId) { for (uint16_t i = CONST_ANI_NONE; i <= CONST_ANI_LAST; i++) { - ShootType_t effect = static_cast<ShootType_t>(i); + auto effect = static_cast<ShootType_t>(i); if (effect == effectId) { return true; } @@ -9978,14 +10085,14 @@ bool Game::hasDistanceEffect(uint16_t effectId) { void Game::createLuaItemsOnMap() { for (const auto [position, itemId] : mapLuaItemsStored) { - std::shared_ptr<Item> item = Item::CreateItem(itemId, 1); + const auto &item = Item::CreateItem(itemId, 1); if (!item) { g_logger().warn("[Game::createLuaItemsOnMap] - Cannot create item with id {}", itemId); continue; } if (position.x != 0) { - std::shared_ptr<Tile> tile = g_game().map.getTile(position); + const auto &tile = g_game().map.getTile(position); if (!tile) { g_logger().warn("[Game::createLuaItemsOnMap] - Tile is wrong or not found position: {}", position.toString()); @@ -10003,7 +10110,7 @@ void Game::createLuaItemsOnMap() { } } -void Game::sendUpdateCreature(std::shared_ptr<Creature> creature) { +void Game::sendUpdateCreature(const std::shared_ptr<Creature> &creature) { if (!creature) { return; } @@ -10020,10 +10127,6 @@ uint32_t Game::makeInfluencedMonster() { return 0; } - if (forgeableMonsters.empty()) { - return 0; - } - auto maxTries = forgeableMonsters.size(); uint16_t tries = 0; std::shared_ptr<Monster> monster = nullptr; @@ -10056,7 +10159,7 @@ uint32_t Game::makeInfluencedMonster() { if (monster && monster->canBeForgeMonster()) { monster->setMonsterForgeClassification(ForgeClassifications_t::FORGE_INFLUENCED_MONSTER); monster->configureForgeSystem(); - influencedMonsters.insert(monster->getID()); + influencedMonsters.emplace(monster->getID()); return monster->getID(); } @@ -10165,7 +10268,7 @@ uint32_t Game::makeFiendishMonster(uint32_t forgeableMonsterId /* = 0*/, bool cr monster->setMonsterForgeClassification(ForgeClassifications_t::FORGE_FIENDISH_MONSTER); monster->configureForgeSystem(); monster->setTimeToChangeFiendish(timeToChangeFiendish + getTimeNow()); - fiendishMonsters.insert(monster->getID()); + fiendishMonsters.emplace(monster->getID()); auto schedulerTask = createPlayerTask( finalTime, @@ -10180,7 +10283,7 @@ uint32_t Game::makeFiendishMonster(uint32_t forgeableMonsterId /* = 0*/, bool cr } void Game::updateFiendishMonsterStatus(uint32_t monsterId, const std::string &monsterName) { - std::shared_ptr<Monster> monster = getMonsterByID(monsterId); + const auto &monster = getMonsterByID(monsterId); if (!monster) { g_logger().warn("[{}] Failed to update monster with id {} and name {}, monster not found", __FUNCTION__, monsterId, monsterName); return; @@ -10248,12 +10351,12 @@ void Game::updateForgeableMonsters() { } if (monster->canBeForgeMonster() && !monsterTile->hasFlag(TILESTATE_NOLOGOUT)) { - forgeableMonsters.push_back(monster->getID()); + forgeableMonsters.emplace_back(monster->getID()); } } } - for (const auto monsterId : getFiendishMonsters()) { + for (const auto &monsterId : getFiendishMonsters()) { if (!getMonsterByID(monsterId)) { removeFiendishMonster(monsterId); } @@ -10293,9 +10396,7 @@ void Game::createInfluencedMonsters() { break; } - if (auto ret = makeInfluencedMonster(); - // If condition - ret == 0) { + if (makeInfluencedMonster() == 0) { return; } @@ -10311,7 +10412,7 @@ void Game::checkForgeEventId(uint32_t monsterId) { } } -bool Game::addInfluencedMonster(std::shared_ptr<Monster> monster) { +bool Game::addInfluencedMonster(const std::shared_ptr<Monster> &monster) { if (monster && monster->canBeForgeMonster()) { if (auto maxInfluencedMonsters = static_cast<uint32_t>(g_configManager().getNumber(FORGE_INFLUENCED_CREATURES_LIMIT)); // If condition @@ -10321,14 +10422,14 @@ bool Game::addInfluencedMonster(std::shared_ptr<Monster> monster) { monster->setMonsterForgeClassification(ForgeClassifications_t::FORGE_INFLUENCED_MONSTER); monster->configureForgeSystem(); - influencedMonsters.insert(monster->getID()); + influencedMonsters.emplace(monster->getID()); return true; } return false; } -bool Game::addItemStoreInbox(std::shared_ptr<Player> player, uint32_t itemId) { - std::shared_ptr<Item> decoKit = Item::CreateItem(ITEM_DECORATION_KIT, 1); +bool Game::addItemStoreInbox(const std::shared_ptr<Player> &player, uint32_t itemId) { + const auto &decoKit = Item::CreateItem(ITEM_DECORATION_KIT, 1); if (!decoKit) { return false; } @@ -10337,17 +10438,17 @@ bool Game::addItemStoreInbox(std::shared_ptr<Player> player, uint32_t itemId) { decoKit->setAttribute(ItemAttribute_t::DESCRIPTION, description); decoKit->setCustomAttribute("unWrapId", static_cast<int64_t>(itemId)); - std::shared_ptr<Thing> thing = player->getThing(CONST_SLOT_STORE_INBOX); + const auto &thing = player->getThing(CONST_SLOT_STORE_INBOX); if (!thing) { return false; } - std::shared_ptr<Item> inboxItem = thing->getItem(); + const auto &inboxItem = thing->getItem(); if (!inboxItem) { return false; } - std::shared_ptr<Container> inboxContainer = inboxItem->getContainer(); + const auto &inboxContainer = inboxItem->getContainer(); if (!inboxContainer) { return false; } @@ -10359,7 +10460,7 @@ bool Game::addItemStoreInbox(std::shared_ptr<Player> player, uint32_t itemId) { return true; } -void Game::addPlayerUniqueLogin(std::shared_ptr<Player> player) { +void Game::addPlayerUniqueLogin(const std::shared_ptr<Player> &player) { if (!player) { g_logger().error("Attempted to add null player to unique player names list"); return; @@ -10389,7 +10490,7 @@ void Game::removePlayerUniqueLogin(const std::string &playerName) { m_uniqueLoginPlayerNames.erase(lowercase_name); } -void Game::removePlayerUniqueLogin(std::shared_ptr<Player> player) { +void Game::removePlayerUniqueLogin(const std::shared_ptr<Player> &player) { if (!player) { g_logger().error("Attempted to remove null player from unique player names list."); return; @@ -10400,14 +10501,13 @@ void Game::removePlayerUniqueLogin(std::shared_ptr<Player> player) { } void Game::playerCheckActivity(const std::string &playerName, int interval) { - std::shared_ptr<Player> player = getPlayerUniqueLogin(playerName); + const auto &player = getPlayerUniqueLogin(playerName); if (!player) { return; } if (player->getIP() == 0) { g_game().removePlayerUniqueLogin(playerName); - IOLoginData::updateOnlineStatus(player->guid, false); g_logger().info("Player with name '{}' has logged out due to exited in death screen", player->getName()); player->disconnect(); return; @@ -10423,7 +10523,6 @@ void Game::playerCheckActivity(const std::string &playerName, int interval) { if (player->m_deathTime > (kickAfterMinutes * 60000) + 60000) { g_logger().info("Player with name '{}' has logged out due to inactivity after death", player->getName()); g_game().removePlayerUniqueLogin(playerName); - IOLoginData::updateOnlineStatus(player->guid, false); player->disconnect(); return; } @@ -10435,18 +10534,18 @@ void Game::playerCheckActivity(const std::string &playerName, int interval) { } void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, uint32_t maxMoveItems /* = 0*/) { - std::shared_ptr<Player> player = getPlayerByID(playerId); + const auto &player = getPlayerByID(playerId); if (!player) { return; } - std::shared_ptr<Thing> thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); + const auto &thing = internalGetThing(player, pos, stackPos, itemId, STACKPOS_FIND_THING); if (!thing) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; } - auto item = thing->getItem(); + const auto &item = thing->getItem(); if (!item || item->getID() != ITEM_REWARD_CHEST || !item->getContainer()) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); return; @@ -10480,9 +10579,9 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint } } -bool Game::tryRetrieveStashItems(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { +bool Game::tryRetrieveStashItems(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { ObjectCategory_t category = getObjectCategory(item); - return internalCollectManagedItems(std::move(player), item, category, false) == RETURNVALUE_NOERROR; + return internalCollectManagedItems(player, item, category, false) == RETURNVALUE_NOERROR; } std::unique_ptr<IOWheel> &Game::getIOWheel() { @@ -10547,7 +10646,7 @@ std::vector<T> setDifference(const std::unordered_set<T> &setA, const std::unord return setResult; } -ReturnValue Game::beforeCreatureZoneChange(std::shared_ptr<Creature> creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones, bool force /* = false*/) const { +ReturnValue Game::beforeCreatureZoneChange(const std::shared_ptr<Creature> &creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones, bool force /* = false*/) const { if (!creature) { return RETURNVALUE_NOTPOSSIBLE; } @@ -10577,7 +10676,8 @@ ReturnValue Game::beforeCreatureZoneChange(std::shared_ptr<Creature> creature, c return RETURNVALUE_NOERROR; } -void Game::afterCreatureZoneChange(std::shared_ptr<Creature> creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones) const { +void Game::afterCreatureZoneChange(const std::shared_ptr<Creature> &creatures, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones) const { + auto creature = creatures; if (!creature) { return; } @@ -10610,7 +10710,7 @@ const std::vector<HighscoreCategory> &Game::getHighscoreCategories() const { return m_highscoreCategories; } -void Game::registerAchievement(uint16_t id, std::string name, std::string description, bool secret, uint8_t grade, uint8_t points) { +void Game::registerAchievement(uint16_t id, const std::string &name, std::string description, bool secret, uint8_t grade, uint8_t points) { m_achievements[id] = Achievement(); m_achievements[id].id = id; m_achievements[id].name = name; @@ -10626,7 +10726,7 @@ Achievement Game::getAchievementById(uint16_t id) { return m_achievements[id]; } -Achievement Game::getAchievementByName(std::string name) { +Achievement Game::getAchievementByName(const std::string &name) { auto it = m_achievementsNameToId.find(name); if (it != m_achievementsNameToId.end()) { return getAchievementById(it->second); @@ -10736,3 +10836,51 @@ const std::unordered_map<uint16_t, std::string> &Game::getHirelingSkills() { const std::unordered_map<uint16_t, std::string> &Game::getHirelingOutfits() { return m_hirelingOutfits; } + +void Game::updatePlayersOnline() const { + // Function to be executed within the transaction + auto updateOperation = [this]() { + const auto &m_players = getPlayers(); + bool changesMade = false; + + // g_metrics().addUpDownCounter("players_online", 1); + // g_metrics().addUpDownCounter("players_online", -1); + + if (m_players.empty()) { + std::string query = "SELECT COUNT(*) AS count FROM players_online;"; + auto result = g_database().storeQuery(query); + int count = result->getNumber<int>("count"); + if (count > 0) { + g_database().executeQuery("DELETE FROM `players_online`;"); + changesMade = true; + } + } else { + // Insert the current players + DBInsert stmt("INSERT IGNORE INTO `players_online` (player_id) VALUES "); + for (const auto &[key, player] : m_players) { + std::ostringstream playerQuery; + playerQuery << "(" << player->getGUID() << ")"; + stmt.addRow(playerQuery.str()); + } + stmt.execute(); + changesMade = true; + + // Remove players who are no longer online + std::ostringstream cleanupQuery; + cleanupQuery << "DELETE FROM `players_online` WHERE `player_id` NOT IN ("; + for (const auto &[key, player] : m_players) { + cleanupQuery << player->getGUID() << ","; + } + cleanupQuery.seekp(-1, std::ostringstream::cur); // Remove the last comma + cleanupQuery << ");"; + g_database().executeQuery(cleanupQuery.str()); + } + + return changesMade; + }; + + const bool success = DBTransaction::executeWithinTransaction(updateOperation); + if (!success) { + g_logger().error("[Game::updatePlayersOnline] Failed to update players online."); + } +} diff --git a/src/game/game.hpp b/src/game/game.hpp index e04dbb26cff..b1afd810100 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -9,22 +9,15 @@ #pragma once -#include "account/account.hpp" -#include "creatures/combat/combat.hpp" -#include "items/containers/container.hpp" +#include "creatures/appearance/outfit/outfit.hpp" +#include "creatures/players/cyclopedia/player_badge.hpp" +#include "creatures/players/cyclopedia/player_title.hpp" +#include "creatures/players/grouping/familiars.hpp" #include "creatures/players/grouping/groups.hpp" -#include "io/iobestiary.hpp" -#include "items/item.hpp" -#include "map/map.hpp" -#include "creatures/npcs/npc.hpp" -#include "movement/position.hpp" -#include "creatures/players/player.hpp" #include "lua/creature/raids.hpp" -#include "creatures/players/grouping/team_finder.hpp" -#include "utils/wildcardtree.hpp" -#include "items/items_classification.hpp" +#include "map/map.hpp" #include "modal_window/modal_window.hpp" -#include "enums/object_category.hpp" +#include "movement/position.hpp" // Forward declaration for protobuf class namespace Canary { @@ -39,7 +32,6 @@ class ServiceManager; class Creature; class Monster; class Npc; -class CombatInfo; class Charm; class IOPrey; class IOWheel; @@ -47,11 +39,25 @@ class ItemClassification; class Guild; class Mounts; class Spectators; +class Player; +class Account; +class TeamFinder; +class NetworkMessage; +class Task; +class Container; +class ContainerIterator; +class Item; +class BedItem; +class WildcardTreeNode; struct Achievement; struct HighscoreCategory; -struct Badge; -struct Title; +struct TextMessage; + +enum ObjectCategory_t : uint8_t; +enum class ForgeAction_t : uint8_t; + +using CreatureVector = std::vector<std::shared_ptr<Creature>>; static constexpr uint16_t SERVER_BEAT = 0x32; static constexpr int32_t EVENT_MS = 10000; @@ -63,6 +69,7 @@ static constexpr int32_t EVENT_LUA_GARBAGE_COLLECTION = 60000 * 10; // 10min static constexpr std::chrono::minutes CACHE_EXPIRATION_TIME { 10 }; // 10min static constexpr std::chrono::minutes HIGHSCORE_CACHE_EXPIRATION_TIME { 10 }; // 10min +static constexpr int32_t UPDATE_PLAYERS_ONLINE_DB = 60000 * 10; // 10min struct QueryHighscoreCacheEntry { std::string query; @@ -87,9 +94,7 @@ class Game { Game(const Game &) = delete; Game &operator=(const Game &) = delete; - static Game &getInstance() { - return inject<Game>(); - } + static Game &getInstance(); void resetMonsters() const; void resetNpcs() const; @@ -129,33 +134,17 @@ class Game { return teamFinderMap; } - const std::unique_ptr<TeamFinder> &getTeamFinder(const std::shared_ptr<Player> &player) const { - auto it = teamFinderMap.find(player->getGUID()); - if (it != teamFinderMap.end()) { - return it->second; - } - - return TeamFinderNull; - } - - const std::unique_ptr<TeamFinder> &getOrCreateTeamFinder(const std::shared_ptr<Player> &player) { - auto it = teamFinderMap.find(player->getGUID()); - if (it != teamFinderMap.end()) { - return it->second; - } + const std::unique_ptr<TeamFinder> &getTeamFinder(const std::shared_ptr<Player> &player) const; - return teamFinderMap[player->getGUID()] = std::make_unique<TeamFinder>(); - } + const std::unique_ptr<TeamFinder> &getOrCreateTeamFinder(const std::shared_ptr<Player> &player); - void removeTeamFinderListed(uint32_t leaderGuid) { - teamFinderMap.erase(leaderGuid); - } + void removeTeamFinderListed(uint32_t leaderGuid); - std::shared_ptr<Cylinder> internalGetCylinder(std::shared_ptr<Player> player, const Position &pos); - std::shared_ptr<Thing> internalGetThing(std::shared_ptr<Player> player, const Position &pos, int32_t index, uint32_t itemId, StackPosType_t type); - static void internalGetPosition(std::shared_ptr<Item> item, Position &pos, uint8_t &stackpos); + std::shared_ptr<Cylinder> internalGetCylinder(const std::shared_ptr<Player> &player, const Position &pos); + std::shared_ptr<Thing> internalGetThing(const std::shared_ptr<Player> &player, const Position &pos, int32_t index, uint32_t itemId, StackPosType_t type); + static void internalGetPosition(const std::shared_ptr<Item> &item, Position &pos, uint8_t &stackpos); - static std::string getTradeErrorDescription(ReturnValue ret, std::shared_ptr<Item> item); + static std::string getTradeErrorDescription(ReturnValue ret, const std::shared_ptr<Item> &item); std::shared_ptr<Creature> getCreatureByID(uint32_t id); @@ -177,13 +166,13 @@ class Game { ReturnValue getPlayerByNameWildcard(const std::string &s, std::shared_ptr<Player> &player); - std::vector<std::shared_ptr<Player>> getPlayersByAccount(std::shared_ptr<Account> acc, bool allowOffline = false); + std::vector<std::shared_ptr<Player>> getPlayersByAccount(const std::shared_ptr<Account> &acc, bool allowOffline = false); - bool internalPlaceCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos = false, bool forced = false, bool creatureCheck = false); + bool internalPlaceCreature(const std::shared_ptr<Creature> &creature, const Position &pos, bool extendedPos = false, bool forced = false, bool creatureCheck = false); - bool placeCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos = false, bool force = false); + bool placeCreature(const std::shared_ptr<Creature> &creature, const Position &pos, bool extendedPos = false, bool force = false); - bool removeCreature(std::shared_ptr<Creature> creature, bool isLogout = true); + bool removeCreature(const std::shared_ptr<Creature> &creature, bool isLogout = true); void executeDeath(uint32_t creatureId); void addCreatureCheck(const std::shared_ptr<Creature> &creature); @@ -205,58 +194,44 @@ class Game { void addItemsClassification(ItemClassification* itemsClassification) { itemsClassifications.push_back(itemsClassification); } - ItemClassification* getItemsClassification(uint8_t id, bool create) { - auto it = std::find_if(itemsClassifications.begin(), itemsClassifications.end(), [id](ItemClassification* it) { - return it->id == id; - }); - - if (it != itemsClassifications.end()) { - return *it; - } else if (create) { - ItemClassification* itemClassification = new ItemClassification(id); - addItemsClassification(itemClassification); - return itemClassification; - } - - return nullptr; - } + ItemClassification* getItemsClassification(uint8_t id, bool create); LightInfo getWorldLightInfo() const; bool gameIsDay(); - ReturnValue internalMoveCreature(std::shared_ptr<Creature> creature, Direction direction, uint32_t flags = 0); + ReturnValue internalMoveCreature(const std::shared_ptr<Creature> &creature, Direction direction, uint32_t flags = 0); ReturnValue internalMoveCreature(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &toTile, uint32_t flags = 0); - ReturnValue checkMoveItemToCylinder(std::shared_ptr<Player> player, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, Position toPos); - ReturnValue internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, int32_t index, std::shared_ptr<Item> item, uint32_t count, std::shared_ptr<Item>* movedItem, uint32_t flags = 0, std::shared_ptr<Creature> actor = nullptr, std::shared_ptr<Item> tradeItem = nullptr, bool checkTile = true); + ReturnValue checkMoveItemToCylinder(const std::shared_ptr<Player> &player, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder, const std::shared_ptr<Item> &item, Position toPos); + ReturnValue internalMoveItem(std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder, int32_t index, const std::shared_ptr<Item> &item, uint32_t count, std::shared_ptr<Item>* movedItem, uint32_t flags = 0, const std::shared_ptr<Creature> &actor = nullptr, const std::shared_ptr<Item> &tradeItem = nullptr, bool checkTile = true); std::tuple<ReturnValue, uint32_t, uint32_t> addItemBatch(const std::shared_ptr<Cylinder> &toCylinder, const std::vector<std::shared_ptr<Item>> &items, uint32_t flags = 0, bool dropOnMap = true, uint32_t autoContainerId = 0); std::tuple<ReturnValue, uint32_t, uint32_t> createItemBatch(const std::shared_ptr<Cylinder> &toCylinder, const std::vector<std::tuple<uint16_t, uint32_t, uint16_t>> &itemCounts, uint32_t flags = 0, bool dropOnMap = true, uint32_t autoContainerId = 0); std::tuple<ReturnValue, uint32_t, uint32_t> createItem(const std::shared_ptr<Cylinder> &toCylinder, uint16_t itemId, uint32_t count, uint16_t subType, uint32_t flags = 0, bool dropOnMap = true, uint32_t autoContainerId = 0); - ReturnValue internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, int32_t index = INDEX_WHEREEVER, uint32_t flags = 0, bool test = false); - ReturnValue internalAddItem(std::shared_ptr<Cylinder> toCylinder, std::shared_ptr<Item> item, int32_t index, uint32_t flags, bool test, uint32_t &remainderCount); - ReturnValue internalRemoveItem(std::shared_ptr<Item> item, int32_t count = -1, bool test = false, uint32_t flags = 0, bool force = false); + ReturnValue internalAddItem(std::shared_ptr<Cylinder> toCylinder, const std::shared_ptr<Item> &item, int32_t index = INDEX_WHEREEVER, uint32_t flags = 0, bool test = false); + ReturnValue internalAddItem(std::shared_ptr<Cylinder> toCylinder, const std::shared_ptr<Item> &item, int32_t index, uint32_t flags, bool test, uint32_t &remainderCount); + ReturnValue internalRemoveItem(const std::shared_ptr<Item> &item, int32_t count = -1, bool test = false, uint32_t flags = 0, bool force = false); - ReturnValue internalPlayerAddItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, bool dropOnMap = true, Slots_t slot = CONST_SLOT_WHEREEVER); + ReturnValue internalPlayerAddItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, bool dropOnMap = true, Slots_t slot = CONST_SLOT_WHEREEVER); - std::shared_ptr<Item> findItemOfType(std::shared_ptr<Cylinder> cylinder, uint16_t itemId, bool depthSearch = true, int32_t subType = -1) const; + std::shared_ptr<Item> findItemOfType(const std::shared_ptr<Cylinder> &cylinder, uint16_t itemId, bool depthSearch = true, int32_t subType = -1) const; void createLuaItemsOnMap(); - bool removeMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint32_t flags = 0, bool useBank = false); + bool removeMoney(const std::shared_ptr<Cylinder> &cylinder, uint64_t money, uint32_t flags = 0, bool useBank = false); - void addMoney(std::shared_ptr<Cylinder> cylinder, uint64_t money, uint32_t flags = 0); + void addMoney(const std::shared_ptr<Cylinder> &cylinder, uint64_t money, uint32_t flags = 0); std::shared_ptr<Item> transformItem(std::shared_ptr<Item> item, uint16_t newId, int32_t newCount = -1); ReturnValue internalTeleport(const std::shared_ptr<Thing> &thing, const Position &newPos, bool pushMove = true, uint32_t flags = 0); - bool internalCreatureTurn(std::shared_ptr<Creature> creature, Direction dir); + bool internalCreatureTurn(const std::shared_ptr<Creature> &creature, Direction dir); - bool internalCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, bool ghostMode, Spectators* spectatorsPtr = nullptr, const Position* pos = nullptr); + bool internalCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, bool ghostMode, Spectators* spectatorsPtr = nullptr, const Position* pos = nullptr); - ObjectCategory_t getObjectCategory(const std::shared_ptr<Item> item); + ObjectCategory_t getObjectCategory(const std::shared_ptr<Item> &item); ObjectCategory_t getObjectCategory(const ItemType &it); uint64_t getItemMarketPrice(const std::map<uint16_t, uint64_t> &itemMap, bool buyPrice) const; @@ -264,8 +239,8 @@ class Game { void loadPlayersRecord(); void checkPlayersRecord(); - void sendSingleSoundEffect(const Position &pos, SoundEffect_t soundId, std::shared_ptr<Creature> actor = nullptr); - void sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundEffect, SoundEffect_t secondarySoundEffect, std::shared_ptr<Creature> actor = nullptr); + void sendSingleSoundEffect(const Position &pos, SoundEffect_t soundId, const std::shared_ptr<Creature> &actor = nullptr); + void sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundEffect, SoundEffect_t secondarySoundEffect, const std::shared_ptr<Creature> &actor = nullptr); void sendGuildMotd(uint32_t playerId); void kickPlayer(uint32_t playerId, bool displayEffect); @@ -297,38 +272,38 @@ class Game { void playerBrowseForgeHistory(uint32_t playerId, uint8_t page); void playerBosstiarySlot(uint32_t playerId, uint8_t slotId, uint32_t selectedBossId); - void playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, const Position &pos, uint8_t stackPos, const uint16_t itemId, uint8_t direction, const std::pair<uint8_t, uint8_t> &podiumAndMonsterVisible); - void playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId); + void playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, const Position &pos, uint8_t stackPos, uint16_t itemId, uint8_t direction, const std::pair<uint8_t, uint8_t> &podiumAndMonsterVisible); + void playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t stackPos, uint16_t itemId); void playerRequestInventoryImbuements(uint32_t playerId, bool isTrackerOpen); - bool addItemStoreInbox(std::shared_ptr<Player> player, uint32_t itemId); + bool addItemStoreInbox(const std::shared_ptr<Player> &player, uint32_t itemId); void playerRewardChestCollect(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, uint32_t maxMoveItems = 0); void playerReportRuleViolationReport(uint32_t playerId, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation); - void playerFriendSystemAction(std::shared_ptr<Player> player, uint8_t type, uint8_t titleId); + void playerFriendSystemAction(const std::shared_ptr<Player> &player, uint8_t type, uint8_t titleId); - void playerCyclopediaCharacterInfo(std::shared_ptr<Player> player, uint32_t characterID, CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage, uint16_t page); + void playerCyclopediaCharacterInfo(const std::shared_ptr<Player> &player, uint32_t characterID, CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage, uint16_t page); - void playerHighscores(std::shared_ptr<Player> player, HighscoreType_t type, uint8_t category, uint32_t vocation, const std::string &worldName, uint16_t page, uint8_t entriesPerPage); + void playerHighscores(const std::shared_ptr<Player> &player, HighscoreType_t type, uint8_t category, uint32_t vocation, const std::string &worldName, uint16_t page, uint8_t entriesPerPage); static std::string getSkillNameById(uint8_t &skill); void updatePlayerSaleItems(uint32_t playerId); - bool internalStartTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> partner, std::shared_ptr<Item> tradeItem); - void internalCloseTrade(std::shared_ptr<Player> player); - bool playerBroadcastMessage(std::shared_ptr<Player> player, const std::string &text) const; + bool internalStartTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &partner, const std::shared_ptr<Item> &tradeItem); + void internalCloseTrade(const std::shared_ptr<Player> &player); + bool playerBroadcastMessage(const std::shared_ptr<Player> &player, const std::string &text) const; void broadcastMessage(const std::string &text, MessageClasses type) const; // Implementation of player invoked events void playerTeleport(uint32_t playerId, const Position &pos); void playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count); void playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, const Position &movingCreatureOrigPos, const Position &toPos); - void playerMoveCreature(std::shared_ptr<Player> playerId, std::shared_ptr<Creature> movingCreature, const Position &movingCreatureOrigPos, std::shared_ptr<Tile> toTile); + void playerMoveCreature(const std::shared_ptr<Player> &playerId, const std::shared_ptr<Creature> &movingCreature, const Position &movingCreatureOrigPos, const std::shared_ptr<Tile> &toTile); void playerMoveItemByPlayerID(uint32_t playerId, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count); - void playerMoveItem(std::shared_ptr<Player> player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr<Item> item, std::shared_ptr<Cylinder> toCylinder); + void playerMoveItem(const std::shared_ptr<Player> &player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr<Item> item, std::shared_ptr<Cylinder> toCylinder); void playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier = false, uint8_t tier = 0); void playerMove(uint32_t playerId, Direction direction); void forcePlayerMove(uint32_t playerId, Direction direction); @@ -353,10 +328,10 @@ class Game { void playerCloseContainer(uint32_t playerId, uint8_t cid); void playerMoveUpContainer(uint32_t playerId, uint8_t cid); void playerUpdateContainer(uint32_t playerId, uint8_t cid); - void playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId); - void playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId); - void playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Position &pos, uint8_t stackPos, const uint16_t itemId, uint8_t podiumVisible, uint8_t direction); - void playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t stackPos, const uint16_t itemId); + void playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stackPos, uint16_t itemId); + void playerConfigureShowOffSocket(uint32_t playerId, const Position &pos, uint8_t stackPos, uint16_t itemId); + void playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Position &pos, uint8_t stackPos, uint16_t itemId, uint8_t podiumVisible, uint8_t direction); + void playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t stackPos, uint16_t itemId); void playerWriteItem(uint32_t playerId, uint32_t windowTextId, const std::string &text); void playerBrowseField(uint32_t playerId, const Position &pos); void playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_t index, uint8_t containerCategory); @@ -375,21 +350,21 @@ class Game { void playerSetFightModes(uint32_t playerId, FightMode_t fightMode, bool chaseMode, bool secureMode); void playerLookAt(uint32_t playerId, uint16_t itemId, const Position &pos, uint8_t stackPos); void playerLookInBattleList(uint32_t playerId, uint32_t creatureId); - void playerQuickLootCorpse(std::shared_ptr<Player> player, std::shared_ptr<Container> corpse, const Position &position); - void playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, std::shared_ptr<Item> defaultItem = nullptr, bool lootAllCorpses = false, bool autoLoot = false); - void playerLootAllCorpses(std::shared_ptr<Player> player, const Position &pos, bool lootAllCorpses); + void playerQuickLootCorpse(const std::shared_ptr<Player> &player, const std::shared_ptr<Container> &corpse, const Position &position); + void playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, const std::shared_ptr<Item> &defaultItem = nullptr, bool lootAllCorpses = false, bool autoLoot = false); + void playerLootAllCorpses(const std::shared_ptr<Player> &player, const Position &pos, bool lootAllCorpses); void playerSetManagedContainer(uint32_t playerId, ObjectCategory_t category, const Position &pos, uint16_t itemId, uint8_t stackPos, bool isLootContainer); void playerClearManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer); void playerOpenManagedContainer(uint32_t playerId, ObjectCategory_t category, bool isLootContainer); void playerSetQuickLootFallback(uint32_t playerId, bool fallback); - void playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t filter, const std::vector<uint16_t> itemIds); + void playerQuickLootBlackWhitelist(uint32_t playerId, QuickLootFilter_t filter, const std::vector<uint16_t> &itemIds); void playerRequestDepotItems(uint32_t playerId); void playerRequestCloseDepotSearch(uint32_t playerId); void playerRequestDepotSearchItem(uint32_t playerId, uint16_t itemId, uint8_t tier); void playerRequestDepotSearchRetrieve(uint32_t playerId, uint16_t itemId, uint8_t tier, uint8_t type); void playerRequestOpenContainerFromDepotSearch(uint32_t playerId, const Position &pos); - void playerMoveThingFromDepotSearch(std::shared_ptr<Player> player, uint16_t itemId, uint8_t tier, uint8_t count, const Position &fromPos, const Position &toPos, bool allItems = false); + void playerMoveThingFromDepotSearch(const std::shared_ptr<Player> &player, uint16_t itemId, uint8_t tier, uint8_t count, const Position &fromPos, const Position &toPos, bool allItems = false); void playerRequestAddVip(uint32_t playerId, const std::string &name); void playerRequestRemoveVip(uint32_t playerId, uint32_t guid); @@ -424,11 +399,11 @@ class Game { void playerSaveWheel(uint32_t playerId, NetworkMessage &msg); void playerWheelGemAction(uint32_t playerId, NetworkMessage &msg); - void updatePlayerHelpers(std::shared_ptr<Player> player); + void updatePlayerHelpers(const std::shared_ptr<Player> &player); void shutdown(); void dieSafely(const std::string &errorMsg); - void addBestiaryList(uint16_t raceid, std::string name); + void addBestiaryList(uint16_t raceid, const std::string &name); const std::map<uint16_t, std::string> &getBestiaryList() const { return BestiaryList; } @@ -445,18 +420,18 @@ class Game { bool canThrowObjectTo(const Position &fromPos, const Position &toPos, SightLines_t lineOfSight = SightLine_CheckSightLine, int32_t rangex = MAP_MAX_CLIENT_VIEW_PORT_X, int32_t rangey = MAP_MAX_CLIENT_VIEW_PORT_Y); bool isSightClear(const Position &fromPos, const Position &toPos, bool sameFloor); - void changeSpeed(std::shared_ptr<Creature> creature, int32_t varSpeedDelta); - void setCreatureSpeed(std::shared_ptr<Creature> creature, int32_t speed); // setCreatureSpeed + void changeSpeed(const std::shared_ptr<Creature> &creature, int32_t varSpeedDelta); + void setCreatureSpeed(const std::shared_ptr<Creature> &creature, int32_t speed); // setCreatureSpeed void changePlayerSpeed(const std::shared_ptr<Player> &player, int32_t varSpeedDelta); - void internalCreatureChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &oufit); - void internalCreatureChangeVisible(std::shared_ptr<Creature> creature, bool visible); - void changeLight(const std::shared_ptr<Creature> creature); - void updateCreatureIcon(const std::shared_ptr<Creature> creature); - void reloadCreature(const std::shared_ptr<Creature> creature); - void updateCreatureSkull(std::shared_ptr<Creature> player); - void updatePlayerShield(std::shared_ptr<Player> player); - void updateCreatureType(std::shared_ptr<Creature> creature); - void updateCreatureWalkthrough(const std::shared_ptr<Creature> creature); + void internalCreatureChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &oufit); + void internalCreatureChangeVisible(const std::shared_ptr<Creature> &creature, bool visible); + void changeLight(const std::shared_ptr<Creature> &creature); + void updateCreatureIcon(const std::shared_ptr<Creature> &creature); + void reloadCreature(const std::shared_ptr<Creature> &creature); + void updateCreatureSkull(const std::shared_ptr<Creature> &player) const; + void updatePlayerShield(const std::shared_ptr<Player> &player); + void updateCreatureType(const std::shared_ptr<Creature> &creature); + void updateCreatureWalkthrough(const std::shared_ptr<Creature> &creature); GameState_t getGameState() const; void setGameState(GameState_t newState); @@ -468,41 +443,41 @@ class Game { void checkCreatures(); void checkLight(); - bool combatBlockHit(CombatDamage &damage, std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, bool checkDefense, bool checkArmor, bool field); + bool combatBlockHit(CombatDamage &damage, const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, bool checkDefense, bool checkArmor, bool field); - void combatGetTypeInfo(CombatType_t combatType, std::shared_ptr<Creature> target, TextColor_t &color, uint16_t &effect); + void combatGetTypeInfo(CombatType_t combatType, const std::shared_ptr<Creature> &target, TextColor_t &color, uint16_t &effect); // Hazard combat helpers - void handleHazardSystemAttack(CombatDamage &damage, std::shared_ptr<Player> player, const std::shared_ptr<Monster> monster, bool isPlayerAttacker); - void notifySpectators(const CreatureVector &spectators, const Position &targetPos, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster); + void handleHazardSystemAttack(CombatDamage &damage, const std::shared_ptr<Player> &player, const std::shared_ptr<Monster> &monster, bool isPlayerAttacker); + void notifySpectators(const CreatureVector &spectators, const Position &targetPos, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster); // Custom PvP System combat helpers - void applyPvPDamage(CombatDamage &damage, std::shared_ptr<Player> attacker, std::shared_ptr<Player> target); - float pvpLevelDifferenceDamageMultiplier(std::shared_ptr<Player> attacker, std::shared_ptr<Player> target); + void applyPvPDamage(CombatDamage &damage, const std::shared_ptr<Player> &attacker, const std::shared_ptr<Player> &target); + float pvpLevelDifferenceDamageMultiplier(const std::shared_ptr<Player> &attacker, const std::shared_ptr<Player> &target); // Wheel of destiny combat helpers - void applyWheelOfDestinyHealing(CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target); - void applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target) const; - int32_t applyHealthChange(CombatDamage &damage, std::shared_ptr<Creature> target) const; + void applyWheelOfDestinyHealing(CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, std::shared_ptr<Creature> target); + void applyWheelOfDestinyEffectsToDamage(CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Creature> &target) const; + int32_t applyHealthChange(const CombatDamage &damage, const std::shared_ptr<Creature> &target) const; - bool combatChangeHealth(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage, bool isEvent = false); - void applyCharmRune(std::shared_ptr<Monster> targetMonster, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Creature> target, const int32_t &realDamage) const; + bool combatChangeHealth(const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, CombatDamage &damage, bool isEvent = false); + void applyCharmRune(const std::shared_ptr<Monster> &targetMonster, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Creature> &target, const int32_t &realDamage) const; void applyManaLeech( - std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster, - std::shared_ptr<Creature> target, const CombatDamage &damage, const int32_t &realDamage + const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, const int32_t &realDamage ) const; void applyLifeLeech( - std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Monster> targetMonster, - std::shared_ptr<Creature> target, const CombatDamage &damage, const int32_t &realDamage + const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Monster> &targetMonster, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, const int32_t &realDamage ) const; int32_t calculateLeechAmount(const int32_t &realDamage, const uint16_t &skillAmount, int targetsAffected) const; - bool combatChangeMana(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage); + bool combatChangeMana(const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, CombatDamage &damage); // Animation help functions - void addCreatureHealth(const std::shared_ptr<Creature> target); - static void addCreatureHealth(const CreatureVector &spectators, const std::shared_ptr<Creature> target); - void addPlayerMana(const std::shared_ptr<Player> target); - void addPlayerVocation(const std::shared_ptr<Player> target); + void addCreatureHealth(const std::shared_ptr<Creature> &target); + static void addCreatureHealth(const CreatureVector &spectators, const std::shared_ptr<Creature> &target); + void addPlayerMana(const std::shared_ptr<Player> &target); + void addPlayerVocation(const std::shared_ptr<Player> &target); void addMagicEffect(const Position &pos, uint16_t effect); static void addMagicEffect(const std::vector<std::shared_ptr<Player>> &players, const Position &pos, uint16_t effect); static void addMagicEffect(const CreatureVector &spectators, const Position &pos, uint16_t effect); @@ -529,7 +504,7 @@ class Game { motdNum++; } - void sendOfflineTrainingDialog(std::shared_ptr<Player> player); + void sendOfflineTrainingDialog(const std::shared_ptr<Player> &player); const std::map<uint16_t, std::map<uint8_t, uint64_t>> &getItemsPrice() const { return itemsPriceMap; @@ -551,18 +526,18 @@ class Game { return itemsClassifications; } - void addPlayer(std::shared_ptr<Player> player); - void removePlayer(std::shared_ptr<Player> player); + void addPlayer(const std::shared_ptr<Player> &player); + void removePlayer(const std::shared_ptr<Player> &player); - void addNpc(std::shared_ptr<Npc> npc); - void removeNpc(std::shared_ptr<Npc> npc); + void addNpc(const std::shared_ptr<Npc> &npc); + void removeNpc(const std::shared_ptr<Npc> &npc); - void addMonster(std::shared_ptr<Monster> npc); - void removeMonster(std::shared_ptr<Monster> npc); + void addMonster(const std::shared_ptr<Monster> &npc); + void removeMonster(const std::shared_ptr<Monster> &npc); std::shared_ptr<Guild> getGuild(uint32_t id, bool allowOffline = false) const; std::shared_ptr<Guild> getGuildByName(const std::string &name, bool allowOffline = false) const; - void addGuild(const std::shared_ptr<Guild> guild); + void addGuild(const std::shared_ptr<Guild> &guild); void removeGuild(uint32_t guildId); phmap::flat_hash_map<std::shared_ptr<Tile>, std::weak_ptr<Container>> browseFields; @@ -581,30 +556,30 @@ class Game { bool hasDistanceEffect(uint16_t effectId); Groups groups; - Familiars familiars; + [[no_unique_address]] Familiars familiars; Map map; - Mounts mounts; - Outfits outfits; + std::unique_ptr<Mounts> mounts; + [[no_unique_address]] Outfits outfits; Raids raids; std::unique_ptr<Canary::protobuf::appearances::Appearances> m_appearancesPtr; auto getTilesToClean() const { return tilesToClean; } - void addTileToClean(std::shared_ptr<Tile> tile) { + void addTileToClean(const std::shared_ptr<Tile> &tile) { tilesToClean.emplace(tile); } - void removeTileToClean(std::shared_ptr<Tile> tile) { + void removeTileToClean(const std::shared_ptr<Tile> &tile) { tilesToClean.erase(tile); } void clearTilesToClean() { tilesToClean.clear(); } - void playerInspectItem(std::shared_ptr<Player> player, const Position &pos); - void playerInspectItem(std::shared_ptr<Player> player, uint16_t itemId, uint8_t itemCount, bool cyclopedia); + void playerInspectItem(const std::shared_ptr<Player> &player, const Position &pos); + void playerInspectItem(const std::shared_ptr<Player> &player, uint16_t itemId, uint8_t itemCount, bool cyclopedia); - void addCharmRune(const std::shared_ptr<Charm> charm) { + void addCharmRune(const std::shared_ptr<Charm> &charm) { CharmList.push_back(charm); CharmList.shrink_to_fit(); } @@ -615,15 +590,15 @@ class Game { FILELOADER_ERRORS loadAppearanceProtobuf(const std::string &file); bool isMagicEffectRegistered(uint16_t type) const { - return std::find(registeredMagicEffects.begin(), registeredMagicEffects.end(), type) != registeredMagicEffects.end(); + return std::ranges::find(registeredMagicEffects, type) != registeredMagicEffects.end(); } bool isDistanceEffectRegistered(uint16_t type) const { - return std::find(registeredDistanceEffects.begin(), registeredDistanceEffects.end(), type) != registeredDistanceEffects.end(); + return std::ranges::find(registeredDistanceEffects, type) != registeredDistanceEffects.end(); } bool isLookTypeRegistered(uint16_t type) const { - return std::find(registeredLookTypes.begin(), registeredLookTypes.end(), type) != registeredLookTypes.end(); + return std::ranges::find(registeredLookTypes, type) != registeredLookTypes.end(); } void setCreateLuaItems(Position position, uint16_t itemId) { @@ -649,9 +624,9 @@ class Game { uint32_t makeFiendishMonster(uint32_t forgeableMonsterId = 0, bool createForgeableMonsters = false); uint32_t makeInfluencedMonster(); - bool addInfluencedMonster(std::shared_ptr<Monster> monster); - void sendUpdateCreature(std::shared_ptr<Creature> creature); - std::shared_ptr<Item> wrapItem(std::shared_ptr<Item> item, std::shared_ptr<House> house); + bool addInfluencedMonster(const std::shared_ptr<Monster> &monster); + void sendUpdateCreature(const std::shared_ptr<Creature> &creature); + std::shared_ptr<Item> wrapItem(const std::shared_ptr<Item> &item, const std::shared_ptr<House> &house); /** * @brief Adds a player to the unique login map. @@ -660,7 +635,7 @@ class Game { * * @param player A pointer to the Player object to add. */ - void addPlayerUniqueLogin(std::shared_ptr<Player> player); + void addPlayerUniqueLogin(const std::shared_ptr<Player> &player); /** * @brief Gets a player from the unique login map using their name. @@ -689,7 +664,7 @@ class Game { * * @param player A pointer to the Player object to remove. */ - void removePlayerUniqueLogin(std::shared_ptr<Player> player); + void removePlayerUniqueLogin(const std::shared_ptr<Player> &player); void playerCheckActivity(const std::string &playerName, int interval); /** @@ -702,10 +677,10 @@ class Game { * @param item Pointer to the item to be checked. * @return True if stash items can be retrieved, false otherwise. */ - bool tryRetrieveStashItems(std::shared_ptr<Player> player, std::shared_ptr<Item> item); + bool tryRetrieveStashItems(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item); - ReturnValue beforeCreatureZoneChange(std::shared_ptr<Creature> creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones, bool force = false) const; - void afterCreatureZoneChange(std::shared_ptr<Creature> creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones) const; + ReturnValue beforeCreatureZoneChange(const std::shared_ptr<Creature> &creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones, bool force = false) const; + void afterCreatureZoneChange(const std::shared_ptr<Creature> &creature, const std::unordered_set<std::shared_ptr<Zone>> &fromZones, const std::unordered_set<std::shared_ptr<Zone>> &toZones) const; std::unique_ptr<IOWheel> &getIOWheel(); const std::unique_ptr<IOWheel> &getIOWheel() const; @@ -717,9 +692,9 @@ class Game { const std::vector<HighscoreCategory> &getHighscoreCategories() const; - void registerAchievement(uint16_t id, std::string name, std::string description, bool secret, uint8_t grade, uint8_t points); + void registerAchievement(uint16_t id, const std::string &name, std::string description, bool secret, uint8_t grade, uint8_t points); Achievement getAchievementById(uint16_t id); - Achievement getAchievementByName(std::string name); + Achievement getAchievementByName(const std::string &name); std::vector<Achievement> getSecretAchievements(); std::vector<Achievement> getPublicAchievements(); std::map<uint16_t, Achievement> getAchievements(); @@ -755,13 +730,13 @@ class Game { std::map<uint32_t, int32_t> forgeMonsterEventIds; std::unordered_set<uint32_t> fiendishMonsters; std::unordered_set<uint32_t> influencedMonsters; - void checkImbuements(); - bool playerSaySpell(std::shared_ptr<Player> player, SpeakClasses type, const std::string &text); - void playerWhisper(std::shared_ptr<Player> player, const std::string &text); - bool playerYell(std::shared_ptr<Player> player, const std::string &text); - bool playerSpeakTo(std::shared_ptr<Player> player, SpeakClasses type, const std::string &receiver, const std::string &text); - void playerSpeakToNpc(std::shared_ptr<Player> player, const std::string &text); - std::shared_ptr<Task> createPlayerTask(uint32_t delay, std::function<void(void)> f, std::string context) const; + void checkImbuements() const; + bool playerSaySpell(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &text); + void playerWhisper(const std::shared_ptr<Player> &player, const std::string &text); + bool playerYell(const std::shared_ptr<Player> &player, const std::string &text); + bool playerSpeakTo(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &receiver, const std::string &text); + void playerSpeakToNpc(const std::shared_ptr<Player> &player, const std::string &text); + std::shared_ptr<Task> createPlayerTask(uint32_t delay, std::function<void(void)> f, const std::string &context) const; /** * @brief Finds the managed container for loot or obtain based on the given parameters. @@ -775,7 +750,7 @@ class Game { * * @return Pointer to the managed container or nullptr if not found. */ - std::shared_ptr<Container> findManagedContainer(std::shared_ptr<Player> player, bool &fallbackConsumed, ObjectCategory_t category, bool isLootContainer); + std::shared_ptr<Container> findManagedContainer(const std::shared_ptr<Player> &player, bool &fallbackConsumed, ObjectCategory_t category, bool isLootContainer); /** * @brief Finds the next available sub-container within a container. @@ -796,7 +771,7 @@ class Game { * @param fallbackConsumed Reference to a boolean flag indicating whether a fallback has been consumed. * @return True if fallback logic was handled, false otherwise. */ - bool handleFallbackLogic(std::shared_ptr<Player> player, std::shared_ptr<Container> &lootContainer, ContainerIterator &containerIterator, const bool &fallbackConsumed); + bool handleFallbackLogic(const std::shared_ptr<Player> &player, std::shared_ptr<Container> &lootContainer, ContainerIterator &containerIterator, const bool &fallbackConsumed); /** * @brief Processes the movement or addition of an item to a loot container. @@ -807,7 +782,7 @@ class Game { * @param player Pointer to the player object. * @return Return value indicating success or error. */ - ReturnValue processMoveOrAddItemToLootContainer(std::shared_ptr<Item> item, std::shared_ptr<Container> lootContainer, uint32_t &remainderCount, std::shared_ptr<Player> player); + ReturnValue processMoveOrAddItemToLootContainer(const std::shared_ptr<Item> &item, const std::shared_ptr<Container> &lootContainer, uint32_t &remainderCount, const std::shared_ptr<Player> &player); /** * @brief Processes loot items and places them into the appropriate containers. @@ -818,7 +793,7 @@ class Game { * @param fallbackConsumed Reference to a boolean flag indicating whether a fallback has been consumed. * @return Return value indicating success or error. */ - ReturnValue processLootItems(std::shared_ptr<Player> player, std::shared_ptr<Container> lootContainer, std::shared_ptr<Item> item, bool &fallbackConsumed); + ReturnValue processLootItems(const std::shared_ptr<Player> &player, std::shared_ptr<Container> lootContainer, const std::shared_ptr<Item> &item, bool &fallbackConsumed); /** * @brief Internally collects loot or obtain items from a given item and places them into the managed container. @@ -828,7 +803,7 @@ class Game { * @param category Category of the item (default is OBJECTCATEGORY_DEFAULT). * @return Return value indicating success or error. */ - ReturnValue internalCollectManagedItems(std::shared_ptr<Player> player, std::shared_ptr<Item> item, ObjectCategory_t category = OBJECTCATEGORY_DEFAULT, bool isLootContainer = true); + ReturnValue internalCollectManagedItems(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, ObjectCategory_t category, bool isLootContainer = true); /** * @brief Collects items from the reward chest. @@ -837,7 +812,7 @@ class Game { * @param maxMoveItems Maximum number of items to move (default is 0, which means no limit). * @return Return value indicating success or error. */ - ReturnValue collectRewardChestItems(std::shared_ptr<Player> player, uint32_t maxMoveItems = 0); + ReturnValue collectRewardChestItems(const std::shared_ptr<Player> &player, uint32_t maxMoveItems = 0); phmap::flat_hash_map<std::string, QueryHighscoreCacheEntry> queryCache; phmap::flat_hash_map<std::string, HighscoreCacheEntry> highscoreCache; @@ -856,10 +831,9 @@ class Game { std::map<Position, uint16_t> mapLuaItemsStored; std::map<uint16_t, std::string> BestiaryList; - std::string boostedCreature = ""; + std::string boostedCreature; std::vector<std::shared_ptr<Charm>> CharmList; - std::vector<std::shared_ptr<Creature>> checkCreatureLists[EVENT_CREATURECOUNT]; std::vector<uint16_t> registeredMagicEffects; std::vector<uint16_t> registeredDistanceEffects; @@ -868,7 +842,7 @@ class Game { size_t lastBucket = 0; size_t lastImbuedBucket = 0; - std::shared_ptr<WildcardTreeNode> wildcardTree; + std::shared_ptr<WildcardTreeNode> wildcardTree = nullptr; std::map<uint32_t, std::shared_ptr<Npc>> npcs; std::map<uint32_t, std::shared_ptr<Monster>> monsters; @@ -919,59 +893,61 @@ class Game { std::vector<ItemClassification*> itemsClassifications; - bool isTryingToStow(const Position &toPos, std::shared_ptr<Cylinder> toCylinder) const; + bool isTryingToStow(const Position &toPos, const std::shared_ptr<Cylinder> &toCylinder) const; void sendDamageMessageAndEffects( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, const Position &targetPos, - std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Player> targetPlayer, TextMessage &message, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, const Position &targetPos, + const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Player> &targetPlayer, TextMessage &message, const CreatureVector &spectators, int32_t realDamage ); - void updatePlayerPartyHuntAnalyzer(const CombatDamage &damage, std::shared_ptr<Player> player) const; + void updatePlayerPartyHuntAnalyzer(const CombatDamage &damage, const std::shared_ptr<Player> &player) const; void sendEffects( - std::shared_ptr<Creature> target, const CombatDamage &damage, const Position &targetPos, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, const Position &targetPos, TextMessage &message, const CreatureVector &spectators ); void sendMessages( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, - const Position &targetPos, std::shared_ptr<Player> attackerPlayer, std::shared_ptr<Player> targetPlayer, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, + const Position &targetPos, const std::shared_ptr<Player> &attackerPlayer, const std::shared_ptr<Player> &targetPlayer, TextMessage &message, const CreatureVector &spectators, int32_t realDamage ) const; bool shouldSendMessage(const TextMessage &message) const; void buildMessageAsAttacker( - std::shared_ptr<Creature> target, const CombatDamage &damage, TextMessage &message, + const std::shared_ptr<Creature> &target, const CombatDamage &damage, TextMessage &message, std::stringstream &ss, const std::string &damageString ) const; void buildMessageAsTarget( - std::shared_ptr<Creature> attacker, const CombatDamage &damage, std::shared_ptr<Player> attackerPlayer, - std::shared_ptr<Player> targetPlayer, TextMessage &message, std::stringstream &ss, + const std::shared_ptr<Creature> &attacker, const CombatDamage &damage, const std::shared_ptr<Player> &attackerPlayer, + const std::shared_ptr<Player> &targetPlayer, TextMessage &message, std::stringstream &ss, const std::string &damageString ) const; void buildMessageAsSpectator( - std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, const CombatDamage &damage, - std::shared_ptr<Player> targetPlayer, TextMessage &message, std::stringstream &ss, + const std::shared_ptr<Creature> &attacker, const std::shared_ptr<Creature> &target, const CombatDamage &damage, + const std::shared_ptr<Player> &targetPlayer, TextMessage &message, std::stringstream &ss, const std::string &damageString, std::string &spectatorMessage ) const; - void unwrapItem(std::shared_ptr<Item> item, uint16_t unWrapId, std::shared_ptr<House> house, std::shared_ptr<Player> player); + void unwrapItem(const std::shared_ptr<Item> &item, uint16_t unWrapId, const std::shared_ptr<House> &house, const std::shared_ptr<Player> &player); // Variable members (m_) std::unique_ptr<IOWheel> m_IOWheel; void cacheQueryHighscore(const std::string &key, const std::string &query, uint32_t page, uint8_t entriesPerPage); - void processHighscoreResults(DBResult_ptr result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage); + void processHighscoreResults(const DBResult_ptr &result, uint32_t playerID, uint8_t category, uint32_t vocation, uint8_t entriesPerPage); std::string generateVocationConditionHighscore(uint32_t vocation); std::string generateHighscoreQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); std::string generateHighscoreQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); std::string generateHighscoreOrGetCachedQueryForEntries(const std::string &categoryName, uint32_t page, uint8_t entriesPerPage, uint32_t vocation); std::string generateHighscoreOrGetCachedQueryForOurRank(const std::string &categoryName, uint8_t entriesPerPage, uint32_t playerGUID, uint32_t vocation); + + void updatePlayersOnline() const; }; constexpr auto g_game = Game::getInstance; diff --git a/src/game/game_definitions.hpp b/src/game/game_definitions.hpp index a6ce6e7eaa8..50fa1307764 100644 --- a/src/game/game_definitions.hpp +++ b/src/game/game_definitions.hpp @@ -54,7 +54,7 @@ enum Faction_t { FACTION_LAST = FACTION_FAFNAR, }; -enum LightState_t { +enum LightState_t : uint8_t { LIGHT_STATE_DAY, LIGHT_STATE_NIGHT, LIGHT_STATE_SUNSET, @@ -94,7 +94,7 @@ enum class HighscoreCategories_t : uint8_t { SHIELDING = 6, FISHING = 7, MAGIC_LEVEL = 8, - LOYALTY = 9, + LOYALTY_POINTS = 9, ACHIEVEMENTS = 10, CHARMS = 11, DROME = 12, diff --git a/src/game/movement/position.cpp b/src/game/movement/position.cpp index 46ea6ea573d..1972f1c2506 100644 --- a/src/game/movement/position.cpp +++ b/src/game/movement/position.cpp @@ -8,6 +8,7 @@ */ #include "game/movement/position.hpp" + #include "utils/tools.hpp" double Position::getEuclideanDistance(const Position &p1, const Position &p2) { diff --git a/src/game/movement/position.hpp b/src/game/movement/position.hpp index 87e74ee3e22..9e298ee4792 100644 --- a/src/game/movement/position.hpp +++ b/src/game/movement/position.hpp @@ -119,7 +119,7 @@ struct Position { namespace std { template <> struct hash<Position> { - std::size_t operator()(const Position &p) const { + std::size_t operator()(const Position &p) const noexcept { return static_cast<std::size_t>(p.x) | (static_cast<std::size_t>(p.y) << 16) | (static_cast<std::size_t>(p.z) << 32); } }; diff --git a/src/game/movement/teleport.cpp b/src/game/movement/teleport.cpp index 5d674e2a93f..d11552220a3 100644 --- a/src/game/movement/teleport.cpp +++ b/src/game/movement/teleport.cpp @@ -7,8 +7,10 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" #include "game/movement/teleport.hpp" + +#include "creatures/creature.hpp" +#include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" Attr_ReadValue Teleport::readAttr(AttrTypes_t attr, PropStream &propStream) { @@ -30,7 +32,7 @@ void Teleport::serializeAttr(PropWriteStream &propWriteStream) const { propWriteStream.write<uint8_t>(destPos.z); } -ReturnValue Teleport::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature>) { +ReturnValue Teleport::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> &) { return RETURNVALUE_NOTPOSSIBLE; } @@ -38,15 +40,15 @@ ReturnValue Teleport::queryMaxCount(int32_t, const std::shared_ptr<Thing> &, uin return RETURNVALUE_NOTPOSSIBLE; } -ReturnValue Teleport::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> /*= nullptr */) { +ReturnValue Teleport::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> & /*= nullptr */) { return RETURNVALUE_NOERROR; } -std::shared_ptr<Cylinder> Teleport::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item>*, uint32_t &) { +std::shared_ptr<Cylinder> Teleport::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item> &, uint32_t &) { return getTeleport(); } -bool Teleport::checkInfinityLoop(std::shared_ptr<Tile> destTile) { +bool Teleport::checkInfinityLoop(const std::shared_ptr<Tile> &destTile) { if (!destTile) { return false; } @@ -61,16 +63,16 @@ bool Teleport::checkInfinityLoop(std::shared_ptr<Tile> destTile) { return false; } -void Teleport::addThing(std::shared_ptr<Thing> thing) { +void Teleport::addThing(const std::shared_ptr<Thing> &thing) { return addThing(0, thing); } -void Teleport::addThing(int32_t, std::shared_ptr<Thing> thing) { +void Teleport::addThing(int32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { return; } - std::shared_ptr<Tile> destTile = g_game().map.getTile(destPos); + const std::shared_ptr<Tile> &destTile = g_game().map.getTile(destPos); if (!destTile) { return; } @@ -78,49 +80,47 @@ void Teleport::addThing(int32_t, std::shared_ptr<Thing> thing) { // Prevent infinity loop if (checkInfinityLoop(destTile)) { const Position &pos = getPosition(); - g_logger().warn("[Teleport:addThing] - " - "Infinity loop teleport at position: {}", - pos.toString()); + g_logger().warn("[Teleport:addThing] - Infinity loop teleport at position: {}", pos.toString()); return; } const MagicEffectClasses effect = Item::items[id].magicEffect; - if (std::shared_ptr<Creature> creature = thing->getCreature()) { + if (const auto &creature = thing->getCreature()) { Position origPos = creature->getPosition(); g_game().internalCreatureTurn(creature, origPos.x > destPos.x ? DIRECTION_WEST : DIRECTION_EAST); - g_dispatcher().addWalkEvent([=] { - g_game().map.moveCreature(creature, destTile); - }); + g_game().map.moveCreature(creature, destTile); + if (effect != CONST_ME_NONE) { g_game().addMagicEffect(origPos, effect); g_game().addMagicEffect(destTile->getPosition(), effect); } - } else if (std::shared_ptr<Item> item = thing->getItem()) { + } else if (const auto &item = thing->getItem()) { if (effect != CONST_ME_NONE) { g_game().addMagicEffect(destTile->getPosition(), effect); g_game().addMagicEffect(item->getPosition(), effect); } + g_game().internalMoveItem(getTile(), destTile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr); } } -void Teleport::updateThing(std::shared_ptr<Thing>, uint16_t, uint32_t) { +void Teleport::updateThing(const std::shared_ptr<Thing> &, uint16_t, uint32_t) { // } -void Teleport::replaceThing(uint32_t, std::shared_ptr<Thing>) { +void Teleport::replaceThing(uint32_t, const std::shared_ptr<Thing> &) { // } -void Teleport::removeThing(std::shared_ptr<Thing>, uint32_t) { +void Teleport::removeThing(const std::shared_ptr<Thing> &, uint32_t) { // } -void Teleport::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { +void Teleport::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); } -void Teleport::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { +void Teleport::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); } diff --git a/src/game/movement/teleport.hpp b/src/game/movement/teleport.hpp index 9e26e1864cf..893cca2610d 100644 --- a/src/game/movement/teleport.hpp +++ b/src/game/movement/teleport.hpp @@ -9,7 +9,10 @@ #pragma once -#include "items/tile.hpp" +#include "items/cylinder.hpp" +#include "items/item.hpp" + +class Tile; class Teleport final : public Item, public Cylinder { public: @@ -20,7 +23,7 @@ class Teleport final : public Item, public Cylinder { return static_self_cast<Teleport>(); } - std::shared_ptr<Cylinder> getCylinder() override final { + std::shared_ptr<Cylinder> getCylinder() override { return getTeleport(); } @@ -32,27 +35,27 @@ class Teleport final : public Item, public Cylinder { return destPos; } void setDestPos(Position pos) { - destPos = std::move(pos); + destPos = pos; } - bool checkInfinityLoop(std::shared_ptr<Tile> destTile); + bool checkInfinityLoop(const std::shared_ptr<Tile> &destTile); // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; - void addThing(std::shared_ptr<Thing> thing) override; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; + void addThing(const std::shared_ptr<Thing> &thing) override; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) override; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; private: Position destPos; diff --git a/src/game/scheduling/dispatcher.cpp b/src/game/scheduling/dispatcher.cpp index a3a767df756..cb27cba23f1 100644 --- a/src/game/scheduling/dispatcher.cpp +++ b/src/game/scheduling/dispatcher.cpp @@ -8,6 +8,7 @@ */ #include "game/scheduling/dispatcher.hpp" + #include "lib/thread/thread_pool.hpp" #include "lib/di/container.hpp" #include "utils/tools.hpp" @@ -243,25 +244,13 @@ void Dispatcher::asyncEvent(std::function<void(void)> &&f, TaskGroup group) { } void Dispatcher::stopEvent(uint64_t eventId) { - const auto &it = scheduledTasksRef.find(eventId); + auto it = scheduledTasksRef.find(eventId); if (it != scheduledTasksRef.end()) { it->second->cancel(); scheduledTasksRef.erase(it); } } -void DispatcherContext::addEvent(std::function<void(void)> &&f, std::string_view context) const { - g_dispatcher().addEvent(std::move(f), context); -} - -void DispatcherContext::tryAddEvent(std::function<void(void)> &&f, std::string_view context) const { - if (!f) { - return; - } - - if (isAsync()) { - g_dispatcher().addEvent(std::move(f), context); - } else { - f(); - } +bool DispatcherContext::isOn() { + return OTSYS_TIME() != 0; } diff --git a/src/game/scheduling/dispatcher.hpp b/src/game/scheduling/dispatcher.hpp index 1b198b58510..d2c6819593c 100644 --- a/src/game/scheduling/dispatcher.hpp +++ b/src/game/scheduling/dispatcher.hpp @@ -33,9 +33,7 @@ enum class DispatcherType : uint8_t { }; struct DispatcherContext { - bool isOn() const { - return OTSYS_TIME() != 0; - } + static bool isOn(); bool isGroup(const TaskGroup _group) const { return group == _group; @@ -57,12 +55,6 @@ struct DispatcherContext { return type; } - // postpone the event - void addEvent(std::function<void(void)> &&f, std::string_view context) const; - - // if the context is async, the event will be postponed, if not, it will be executed immediately. - void tryAddEvent(std::function<void(void)> &&f, std::string_view context) const; - private: void reset() { group = TaskGroup::ThreadPool; @@ -90,7 +82,9 @@ class Dispatcher { for (uint_fast16_t i = 0; i < threads.capacity(); ++i) { threads.emplace_back(std::make_unique<ThreadTask>()); } - }; + + scheduledTasksRef.reserve(2000); + } // Ensures that we don't accidentally copy it Dispatcher(const Dispatcher &) = delete; @@ -215,12 +209,13 @@ class Dispatcher { std::vector<std::shared_ptr<Task>> scheduledTasks; std::mutex mutex; }; + std::vector<std::unique_ptr<ThreadTask>> threads; // Main Events std::array<std::vector<Task>, static_cast<uint8_t>(TaskGroup::Last)> m_tasks; - phmap::btree_multiset<std::shared_ptr<Task>, Task::Compare> scheduledTasks; - phmap::parallel_flat_hash_map_m<uint64_t, std::shared_ptr<Task>> scheduledTasksRef; + phmap::btree_multiset<std::shared_ptr<Task>, Task::Compare> scheduledTasks {}; + phmap::parallel_flat_hash_map_m<uint64_t, std::shared_ptr<Task>> scheduledTasksRef {}; bool asyncWaitDisabled = false; diff --git a/src/game/scheduling/events_scheduler.cpp b/src/game/scheduling/events_scheduler.cpp index 44005fce11f..4a9bb017335 100644 --- a/src/game/scheduling/events_scheduler.cpp +++ b/src/game/scheduling/events_scheduler.cpp @@ -7,8 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ -#include "config/configmanager.hpp" #include "game/scheduling/events_scheduler.hpp" + +#include "config/configmanager.hpp" #include "lua/scripts/scripts.hpp" bool EventsScheduler::loadScheduleEventFromXml() { diff --git a/src/game/scheduling/events_scheduler.hpp b/src/game/scheduling/events_scheduler.hpp index 6c8233d8b0e..fe56aeb9a12 100644 --- a/src/game/scheduling/events_scheduler.hpp +++ b/src/game/scheduling/events_scheduler.hpp @@ -87,7 +87,7 @@ class EventsScheduler { std::vector<EventScheduler> eventScheduler; - std::string join(const std::vector<std::string> &vec, const std::string &delim); + static std::string join(const std::vector<std::string> &vec, const std::string &delim); }; constexpr auto g_eventsScheduler = EventsScheduler::getInstance; diff --git a/src/game/scheduling/save_manager.cpp b/src/game/scheduling/save_manager.cpp index 254786f747d..45cd9392194 100644 --- a/src/game/scheduling/save_manager.cpp +++ b/src/game/scheduling/save_manager.cpp @@ -9,9 +9,14 @@ #include "game/scheduling/save_manager.hpp" +#include "config/configmanager.hpp" +#include "creatures/players/grouping/guild.hpp" #include "game/game.hpp" +#include "io/ioguild.hpp" #include "io/iologindata.hpp" #include "kv/kv.hpp" +#include "lib/di/container.hpp" +#include "creatures/players/player.hpp" SaveManager::SaveManager(ThreadPool &threadPool, KVStore &kvStore, Logger &logger, Game &game) : threadPool(threadPool), kv(kvStore), logger(logger), game(game) { } diff --git a/src/game/scheduling/task.cpp b/src/game/scheduling/task.cpp index 8e1b984a905..1edd246a702 100644 --- a/src/game/scheduling/task.cpp +++ b/src/game/scheduling/task.cpp @@ -7,14 +7,17 @@ * Website: https://docs.opentibiabr.com/ */ -#include "task.hpp" +#include "game/scheduling/task.hpp" #include "lib/metrics/metrics.hpp" +#include "utils/tools.hpp" + std::atomic_uint_fast64_t Task::LAST_EVENT_ID = 0; Task::Task(uint32_t expiresAfterMs, std::function<void(void)> &&f, std::string_view context) : - func(std::move(f)), context(context), utime(OTSYS_TIME()), expiration(expiresAfterMs > 0 ? OTSYS_TIME() + expiresAfterMs : 0) { + func(std::move(f)), context(context), utime(OTSYS_TIME()), + expiration(expiresAfterMs > 0 ? OTSYS_TIME() + expiresAfterMs : 0) { if (this->context.empty()) { g_logger().error("[{}]: task context cannot be empty!", __FUNCTION__); return; @@ -24,7 +27,8 @@ Task::Task(uint32_t expiresAfterMs, std::function<void(void)> &&f, std::string_v } Task::Task(std::function<void(void)> &&f, std::string_view context, uint32_t delay, bool cycle /* = false*/, bool log /*= true*/) : - func(std::move(f)), context(context), utime(OTSYS_TIME() + delay), delay(delay), cycle(cycle), log(log) { + func(std::move(f)), context(context), utime(OTSYS_TIME() + delay), delay(delay), + cycle(cycle), log(log) { if (this->context.empty()) { g_logger().error("[{}]: task context cannot be empty!", __FUNCTION__); return; @@ -33,6 +37,10 @@ Task::Task(std::function<void(void)> &&f, std::string_view context, uint32_t del assert(!this->context.empty() && "Context cannot be empty!"); } +[[nodiscard]] bool Task::hasExpired() const { + return expiration != 0 && expiration < OTSYS_TIME(); +} + bool Task::execute() const { metrics::task_latency measure(context); if (isCanceled()) { @@ -53,6 +61,9 @@ bool Task::execute() const { } func(); - return true; } + +void Task::updateTime() { + utime = OTSYS_TIME() + delay; +} diff --git a/src/game/scheduling/task.hpp b/src/game/scheduling/task.hpp index 3f134abf728..6cd9eef342d 100644 --- a/src/game/scheduling/task.hpp +++ b/src/game/scheduling/task.hpp @@ -8,8 +8,8 @@ */ #pragma once -#include "utils/tools.hpp" -#include <unordered_set> + +class Dispatcher; class Task { public: @@ -24,34 +24,30 @@ class Task { if (++LAST_EVENT_ID == 0) { LAST_EVENT_ID = 1; } - id = LAST_EVENT_ID; } - return id; } - uint32_t getDelay() const { + [[nodiscard]] uint32_t getDelay() const { return delay; } - std::string_view getContext() const { + [[nodiscard]] std::string_view getContext() const { return context; } - auto getTime() const { + [[nodiscard]] auto getTime() const { return utime; } - bool hasExpired() const { - return expiration != 0 && expiration < OTSYS_TIME(); - } + [[nodiscard]] bool hasExpired() const; - bool isCycle() const { + [[nodiscard]] bool isCycle() const { return cycle; } - bool isCanceled() const { + [[nodiscard]] bool isCanceled() const { return func == nullptr; } @@ -64,56 +60,54 @@ class Task { private: static std::atomic_uint_fast64_t LAST_EVENT_ID; - void updateTime() { - utime = OTSYS_TIME() + delay; - } + void updateTime(); bool hasTraceableContext() const { - const static auto tasksContext = std::unordered_set<std::string_view>({ "Decay::checkDecay", - "Dispatcher::asyncEvent", - "Game::checkCreatureAttack", - "Game::checkCreatureWalk", - "Game::checkCreatures", - "Game::checkImbuements", - "Game::checkLight", - "Game::createFiendishMonsters", - "Game::createInfluencedMonsters", - "Game::updateCreatureWalk", - "Game::updateForgeableMonsters", - "GlobalEvents::think", - "LuaEnvironment::executeTimerEvent", - "Modules::executeOnRecvbyte", - "Monster::onCreatureMove", - "OutputMessagePool::sendAll", - "ProtocolGame::addGameTask", - "ProtocolGame::parsePacketFromDispatcher", - "Raids::checkRaids", - "SpawnMonster::checkSpawnMonster", - "SpawnMonster::scheduleSpawn", - "SpawnMonster::startup", - "SpawnNpc::checkSpawnNpc", - "Webhook::run", - "Protocol::sendRecvMessageCallback", - "Player::addInFightTicks" }); + const static std::unordered_set<std::string_view> tasksContext = { + "Decay::checkDecay", + "Dispatcher::asyncEvent", + "Game::checkCreatureAttack", + "Game::checkCreatureWalk", + "Game::checkCreatures", + "Game::checkImbuements", + "Game::checkLight", + "Game::createFiendishMonsters", + "Game::createInfluencedMonsters", + "Game::updateCreatureWalk", + "Game::updateForgeableMonsters", + "Game::addCreatureCheck", + "GlobalEvents::think", + "LuaEnvironment::executeTimerEvent", + "Modules::executeOnRecvbyte", + "OutputMessagePool::sendAll", + "ProtocolGame::addGameTask", + "ProtocolGame::parsePacketFromDispatcher", + "Raids::checkRaids", + "SpawnMonster::checkSpawnMonster", + "SpawnMonster::scheduleSpawn", + "SpawnMonster::startup", + "SpawnNpc::checkSpawnNpc", + "Webhook::run", + "Protocol::sendRecvMessageCallback", + "Player::addInFightTicks" + }; return tasksContext.contains(context); } struct Compare { bool operator()(const std::shared_ptr<Task> &a, const std::shared_ptr<Task> &b) const { - return a->utime < b->utime; + return a->getTime() < b->getTime(); } }; - std::function<void(void)> func = nullptr; + std::function<void(void)> func; std::string context; int64_t utime = 0; int64_t expiration = 0; - uint64_t id = 0; uint32_t delay = 0; - bool cycle = false; bool log = true; diff --git a/src/game/zones/zone.cpp b/src/game/zones/zone.cpp index 9215ef2570f..6f9f36886ea 100644 --- a/src/game/zones/zone.cpp +++ b/src/game/zones/zone.cpp @@ -7,7 +7,8 @@ * Website: https://docs.opentibiabr.com/ */ -#include "zone.hpp" +#include "game/zones/zone.hpp" + #include "game/game.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/npcs/npc.hpp" @@ -253,11 +254,11 @@ void Zone::refresh() { void Zone::setMonsterVariant(const std::string &variant) { monsterVariant = variant; g_logger().debug("Zone {} monster variant set to {}", name, variant); - for (auto &spawnMonster : g_game().map.spawnsMonster.getspawnMonsterList()) { - if (!contains(spawnMonster.getCenterPos())) { + for (const auto &spawnMonster : g_game().map.spawnsMonster.getspawnMonsterList()) { + if (!contains(spawnMonster->getCenterPos())) { continue; } - spawnMonster.setMonsterVariant(variant); + spawnMonster->setMonsterVariant(variant); } removeMonsters(); diff --git a/src/game/zones/zone.hpp b/src/game/zones/zone.hpp index 82969a25792..a3af961bd7f 100644 --- a/src/game/zones/zone.hpp +++ b/src/game/zones/zone.hpp @@ -143,8 +143,8 @@ namespace weak { class Zone { public: - explicit Zone(const std::string &name, uint32_t id = 0) : - name(name), id(id) { } + explicit Zone(std::string name, uint32_t id = 0) : + name(std::move(name)), id(id) { } explicit Zone(uint32_t id) : id(id) { } @@ -199,7 +199,7 @@ class Zone { static std::shared_ptr<Zone> addZone(const std::string &name, uint32_t id = 0); static std::shared_ptr<Zone> getZone(const std::string &name); static std::shared_ptr<Zone> getZone(uint32_t id); - static std::vector<std::shared_ptr<Zone>> getZones(const Position position); + static std::vector<std::shared_ptr<Zone>> getZones(Position position); static std::vector<std::shared_ptr<Zone>> getZones(); static void refreshAll() { for (const auto &[_, zone] : zones) { diff --git a/src/io/fileloader.cpp b/src/io/fileloader.cpp index a4269ffdd30..c62901f5c51 100644 --- a/src/io/fileloader.cpp +++ b/src/io/fileloader.cpp @@ -20,7 +20,9 @@ namespace OTB { } Identifier fileIdentifier; - std::copy(fileContents.begin(), fileContents.begin() + fileIdentifier.size(), fileIdentifier.begin()); + + std::ranges::copy(fileContents | std::views::take(fileIdentifier.size()), fileIdentifier.begin()); + if (fileIdentifier != acceptedIdentifier && fileIdentifier != wildcard) { throw InvalidOTBFormat {}; } diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index 5b2621c1cbf..e724d0ceda9 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -7,29 +7,47 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/players/wheel/player_wheel.hpp" -#include "creatures/players/achievement/player_achievement.hpp" #include "io/functions/iologindata_load_player.hpp" -#include "game/game.hpp" -#include "enums/object_category.hpp" + +#include "account/account.hpp" +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" +#include "database/database.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/players/achievement/player_achievement.hpp" +#include "creatures/players/cyclopedia/player_badge.hpp" +#include "creatures/players/cyclopedia/player_cyclopedia.hpp" +#include "creatures/players/cyclopedia/player_title.hpp" +#include "creatures/players/vip/player_vip.hpp" +#include "creatures/players/vocations/vocation.hpp" +#include "creatures/players/wheel/player_wheel.hpp" #include "enums/account_coins.hpp" #include "enums/account_errors.hpp" +#include "enums/object_category.hpp" +#include "game/game.hpp" +#include "io/ioguild.hpp" +#include "io/ioprey.hpp" +#include "items/containers/depot/depotchest.hpp" +#include "items/containers/inbox/inbox.hpp" +#include "items/containers/rewards/reward.hpp" +#include "items/containers/rewards/rewardchest.hpp" +#include "creatures/players/player.hpp" #include "utils/tools.hpp" -void IOLoginDataLoad::loadItems(ItemsMap &itemsMap, DBResult_ptr result, const std::shared_ptr<Player> &player) { +void IOLoginDataLoad::loadItems(ItemsMap &itemsMap, const DBResult_ptr &result, const std::shared_ptr<Player> &player) { try { do { - uint32_t sid = result->getNumber<uint32_t>("sid"); - uint32_t pid = result->getNumber<uint32_t>("pid"); - uint16_t type = result->getNumber<uint16_t>("itemtype"); - uint16_t count = result->getNumber<uint16_t>("count"); + auto sid = result->getNumber<uint32_t>("sid"); + auto pid = result->getNumber<uint32_t>("pid"); + auto type = result->getNumber<uint16_t>("itemtype"); + auto count = result->getNumber<uint16_t>("count"); unsigned long attrSize; const char* attr = result->getStream("attributes", attrSize); PropStream propStream; propStream.init(attr, attrSize); try { - std::shared_ptr<Item> item = Item::CreateItem(type, count); + const auto &item = Item::CreateItem(type, count); if (item) { if (!item->unserializeAttr(propStream)) { g_logger().warn("[{}] - Failed to deserialize item attributes {}, from player {}, from account id {}", __FUNCTION__, item->getID(), player->getName(), player->getAccountId()); @@ -49,7 +67,7 @@ void IOLoginDataLoad::loadItems(ItemsMap &itemsMap, DBResult_ptr result, const s } } -bool IOLoginDataLoad::preLoadPlayer(std::shared_ptr<Player> player, const std::string &name) { +bool IOLoginDataLoad::preLoadPlayer(const std::shared_ptr<Player> &player, const std::string &name) { Database &db = Database::getInstance(); std::ostringstream query; @@ -77,16 +95,16 @@ bool IOLoginDataLoad::preLoadPlayer(std::shared_ptr<Player> player, const std::s return false; } - auto [coins, error] = player->account->getCoins(enumToValue(CoinType::Normal)); - if (error != enumToValue(AccountErrors_t::Ok)) { + auto [coins, error] = player->account->getCoins(CoinType::Normal); + if (error != AccountErrors_t::Ok) { g_logger().error("Failed to get coins for player {}, error {}", player->name, static_cast<uint8_t>(error)); return false; } player->coinBalance = coins; - auto [transferableCoins, errorT] = player->account->getCoins(enumToValue(CoinType::Transferable)); - if (errorT != enumToValue(AccountErrors_t::Ok)) { + auto [transferableCoins, errorT] = player->account->getCoins(CoinType::Transferable); + if (errorT != AccountErrors_t::Ok) { g_logger().error("Failed to get transferable coins for player {}, error {}", player->name, static_cast<uint8_t>(errorT)); return false; } @@ -103,7 +121,7 @@ bool IOLoginDataLoad::preLoadPlayer(std::shared_ptr<Player> player, const std::s return true; } -bool IOLoginDataLoad::loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResult_ptr result) { +bool IOLoginDataLoad::loadPlayerBasicInfo(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return false; @@ -139,7 +157,7 @@ bool IOLoginDataLoad::loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResu player->manaMax = result->getNumber<uint32_t>("manamax"); player->magLevel = result->getNumber<uint32_t>("maglevel"); uint64_t nextManaCount = player->vocation->getReqMana(player->magLevel + 1); - uint64_t manaSpent = result->getNumber<uint64_t>("manaspent"); + auto manaSpent = result->getNumber<uint64_t>("manaspent"); if (manaSpent > nextManaCount) { manaSpent = 0; } @@ -164,10 +182,28 @@ bool IOLoginDataLoad::loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResu player->setOfflineTrainingSkill(skill); const auto &town = g_game().map.towns.getTown(result->getNumber<uint32_t>("town_id")); if (!town) { - g_logger().error("Player {} has town id {} which doesn't exist", player->name, result->getNumber<uint16_t>("town_id")); - return false; + g_logger().error("Player {} has invalid town id {}. Attempting to set the correct town.", player->name, result->getNumber<uint16_t>("town_id")); + + const auto &thaisTown = g_game().map.towns.getTown("Thais"); + if (thaisTown) { + player->town = thaisTown; + g_logger().warn("Assigned town 'Thais' to player {}", player->name); + } else { + for (const auto &[townId, currentTown] : g_game().map.towns.getTowns()) { + if (townId != 0 && currentTown) { + player->town = currentTown; + g_logger().warn("Assigned first valid town {} (id: {}) to player {}", currentTown->getName(), townId, player->name); + } + } + + if (!player->town) { + g_logger().error("Player {} has invalid town id {}. No valid town found to assign.", player->name, result->getNumber<uint16_t>("town_id")); + return false; + } + } + } else { + player->town = town; } - player->town = town; const Position &loginPos = player->loginPosition; if (loginPos.x == 0 && loginPos.y == 0 && loginPos.z == 0) { @@ -185,13 +221,13 @@ bool IOLoginDataLoad::loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResu return true; } -void IOLoginDataLoad::loadPlayerExperience(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerExperience(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; } - uint64_t experience = result->getNumber<uint64_t>("experience"); + auto experience = result->getNumber<uint64_t>("experience"); uint64_t currExpCount = Player::getExpForLevel(player->level); uint64_t nextExpCount = Player::getExpForLevel(player->level + 1); @@ -208,7 +244,7 @@ void IOLoginDataLoad::loadPlayerExperience(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerBlessings(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerBlessings(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -219,7 +255,7 @@ void IOLoginDataLoad::loadPlayerBlessings(std::shared_ptr<Player> player, DBResu } } -void IOLoginDataLoad::loadPlayerConditions(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerConditions(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -239,7 +275,7 @@ void IOLoginDataLoad::loadPlayerConditions(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerDefaultOutfit(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -270,7 +306,7 @@ void IOLoginDataLoad::loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DB player->currentOutfit = player->defaultOutfit; } -void IOLoginDataLoad::loadPlayerSkullSystem(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerSkullSystem(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -282,7 +318,7 @@ void IOLoginDataLoad::loadPlayerSkullSystem(std::shared_ptr<Player> player, DBRe // ensure that we round up the number of ticks player->skullTicks = (skullSeconds + 2); - uint16_t skull = result->getNumber<uint16_t>("skull"); + auto skull = result->getNumber<uint16_t>("skull"); if (skull == SKULL_RED) { player->skull = SKULL_RED; } else if (skull == SKULL_BLACK) { @@ -292,7 +328,7 @@ void IOLoginDataLoad::loadPlayerSkullSystem(std::shared_ptr<Player> player, DBRe } } -void IOLoginDataLoad::loadPlayerSkill(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerSkill(const std::shared_ptr<Player> &player, const DBResult_ptr &result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -301,8 +337,8 @@ void IOLoginDataLoad::loadPlayerSkill(std::shared_ptr<Player> player, DBResult_p static const std::array<std::string, 13> skillNames = { "skill_fist", "skill_club", "skill_sword", "skill_axe", "skill_dist", "skill_shielding", "skill_fishing", "skill_critical_hit_chance", "skill_critical_hit_damage", "skill_life_leech_chance", "skill_life_leech_amount", "skill_mana_leech_chance", "skill_mana_leech_amount" }; static const std::array<std::string, 13> skillNameTries = { "skill_fist_tries", "skill_club_tries", "skill_sword_tries", "skill_axe_tries", "skill_dist_tries", "skill_shielding_tries", "skill_fishing_tries", "skill_critical_hit_chance_tries", "skill_critical_hit_damage_tries", "skill_life_leech_chance_tries", "skill_life_leech_amount_tries", "skill_mana_leech_chance_tries", "skill_mana_leech_amount_tries" }; for (size_t i = 0; i < skillNames.size(); ++i) { - uint16_t skillLevel = result->getNumber<uint16_t>(skillNames[i]); - uint64_t skillTries = result->getNumber<uint64_t>(skillNameTries[i]); + auto skillLevel = result->getNumber<uint16_t>(skillNames[i]); + auto skillTries = result->getNumber<uint64_t>(skillNameTries[i]); uint64_t nextSkillTries = player->vocation->getReqSkillTries(static_cast<uint8_t>(i), skillLevel + 1); if (skillTries > nextSkillTries) { skillTries = 0; @@ -314,7 +350,7 @@ void IOLoginDataLoad::loadPlayerSkill(std::shared_ptr<Player> player, DBResult_p } } -void IOLoginDataLoad::loadPlayerKills(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerKills(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -325,7 +361,7 @@ void IOLoginDataLoad::loadPlayerKills(std::shared_ptr<Player> player, DBResult_p query << "SELECT `player_id`, `time`, `target`, `unavenged` FROM `player_kills` WHERE `player_id` = " << player->getGUID(); if ((result = db.storeQuery(query.str()))) { do { - time_t killTime = result->getNumber<time_t>("time"); + auto killTime = result->getNumber<time_t>("time"); if ((time(nullptr) - killTime) <= g_configManager().getNumber(FRAG_TIME)) { player->unjustifiedKills.emplace_back(result->getNumber<uint32_t>("target"), killTime, result->getNumber<bool>("unavenged")); } @@ -333,7 +369,7 @@ void IOLoginDataLoad::loadPlayerKills(std::shared_ptr<Player> player, DBResult_p } } -void IOLoginDataLoad::loadPlayerGuild(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerGuild(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -343,8 +379,8 @@ void IOLoginDataLoad::loadPlayerGuild(std::shared_ptr<Player> player, DBResult_p std::ostringstream query; query << "SELECT `guild_id`, `rank_id`, `nick` FROM `guild_membership` WHERE `player_id` = " << player->getGUID(); if ((result = db.storeQuery(query.str()))) { - uint32_t guildId = result->getNumber<uint32_t>("guild_id"); - uint32_t playerRankId = result->getNumber<uint32_t>("rank_id"); + auto guildId = result->getNumber<uint32_t>("guild_id"); + auto playerRankId = result->getNumber<uint32_t>("rank_id"); player->guildNick = result->getString("nick"); auto guild = g_game().getGuild(guildId); @@ -383,7 +419,7 @@ void IOLoginDataLoad::loadPlayerGuild(std::shared_ptr<Player> player, DBResult_p } } -void IOLoginDataLoad::loadPlayerStashItems(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerStashItems(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -399,7 +435,7 @@ void IOLoginDataLoad::loadPlayerStashItems(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerBestiaryCharms(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerBestiaryCharms(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -452,7 +488,7 @@ void IOLoginDataLoad::loadPlayerBestiaryCharms(std::shared_ptr<Player> player, D } } -void IOLoginDataLoad::loadPlayerInstantSpellList(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerInstantSpellList(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; @@ -468,7 +504,7 @@ void IOLoginDataLoad::loadPlayerInstantSpellList(std::shared_ptr<Player> player, } } -void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerInventoryItems(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -485,9 +521,9 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, D if ((result = g_database().storeQuery(query))) { loadItems(inventoryItems, result, player); - for (ItemsMap::const_reverse_iterator it = inventoryItems.rbegin(), end = inventoryItems.rend(); it != end; ++it) { + for (auto it = inventoryItems.rbegin(), end = inventoryItems.rend(); it != end; ++it) { const std::pair<std::shared_ptr<Item>, int32_t> &pair = it->second; - const std::shared_ptr<Item> &item = pair.first; + const auto &item = pair.first; if (!item) { continue; } @@ -515,13 +551,13 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, D if (!oldProtocol) { auto cid = item->getAttribute<int64_t>(ItemAttribute_t::OPENCONTAINER); if (cid > 0) { - openContainersList.emplace_back(std::make_pair(cid, itemContainer)); + openContainersList.emplace_back(cid, itemContainer); } } - for (bool isLootContainer : { true, false }) { - auto checkAttribute = isLootContainer ? ItemAttribute_t::QUICKLOOTCONTAINER : ItemAttribute_t::OBTAINCONTAINER; + for (const bool isLootContainer : { true, false }) { + const auto checkAttribute = isLootContainer ? ItemAttribute_t::QUICKLOOTCONTAINER : ItemAttribute_t::OBTAINCONTAINER; if (item->hasAttribute(checkAttribute)) { - auto flags = item->getAttribute<uint32_t>(checkAttribute); + const auto flags = item->getAttribute<uint32_t>(checkAttribute); for (uint8_t category = OBJECTCATEGORY_FIRST; category <= OBJECTCATEGORY_LAST; category++) { if (hasBitSet(1 << category, flags)) { @@ -555,7 +591,7 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr<Player> player, D } } -void IOLoginDataLoad::loadPlayerStoreInbox(std::shared_ptr<Player> player) { +void IOLoginDataLoad::loadPlayerStoreInbox(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; @@ -566,7 +602,7 @@ void IOLoginDataLoad::loadPlayerStoreInbox(std::shared_ptr<Player> player) { } } -void IOLoginDataLoad::loadRewardItems(std::shared_ptr<Player> player) { +void IOLoginDataLoad::loadRewardItems(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; @@ -584,7 +620,7 @@ void IOLoginDataLoad::loadRewardItems(std::shared_ptr<Player> player) { } } -void IOLoginDataLoad::loadPlayerDepotItems(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerDepotItems(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -595,24 +631,27 @@ void IOLoginDataLoad::loadPlayerDepotItems(std::shared_ptr<Player> player, DBRes auto query = fmt::format("SELECT pid, sid, itemtype, count, attributes FROM player_depotitems WHERE player_id = {} ORDER BY sid DESC", player->getGUID()); if ((result = g_database().storeQuery(query))) { loadItems(depotItems, result, player); - for (ItemsMap::const_reverse_iterator it = depotItems.rbegin(), end = depotItems.rend(); it != end; ++it) { + for (auto it = depotItems.rbegin(), end = depotItems.rend(); it != end; ++it) { const std::pair<std::shared_ptr<Item>, int32_t> &pair = it->second; - std::shared_ptr<Item> item = pair.first; + const auto &item = pair.first; + if (!item) { + continue; + } int32_t pid = pair.second; if (pid >= 0 && pid < 100) { - std::shared_ptr<DepotChest> depotChest = player->getDepotChest(pid, true); + const std::shared_ptr<DepotChest> &depotChest = player->getDepotChest(pid, true); if (depotChest) { depotChest->internalAddThing(item); item->startDecaying(); } } else { - ItemsMap::const_iterator it2 = depotItems.find(pid); - if (it2 == depotItems.end()) { + auto depotIt = depotItems.find(pid); + if (depotIt == depotItems.end()) { continue; } - std::shared_ptr<Container> container = it2->second.first->getContainer(); + const std::shared_ptr<Container> &container = depotIt->second.first->getContainer(); if (container) { container->internalAddThing(item); // Here, the sub-containers do not yet have a parent, since the main backpack has not yet been added to the player, so we need to postpone @@ -628,7 +667,7 @@ void IOLoginDataLoad::loadPlayerDepotItems(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerInboxItems(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerInboxItems(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -640,20 +679,30 @@ void IOLoginDataLoad::loadPlayerInboxItems(std::shared_ptr<Player> player, DBRes ItemsMap inboxItems; loadItems(inboxItems, result, player); - for (ItemsMap::const_reverse_iterator it = inboxItems.rbegin(), end = inboxItems.rend(); it != end; ++it) { - const std::pair<std::shared_ptr<Item>, int32_t> &pair = it->second; - std::shared_ptr<Item> item = pair.first; + const auto &playerInbox = player->getInbox(); + if (!playerInbox) { + g_logger().warn("[{}] - Player inbox nullptr", __FUNCTION__); + return; + } + + for (const auto &it : std::ranges::reverse_view(inboxItems)) { + const std::pair<std::shared_ptr<Item>, int32_t> &pair = it.second; + const auto &item = pair.first; + if (!item) { + continue; + } + int32_t pid = pair.second; if (pid >= 0 && pid < 100) { - player->getInbox()->internalAddThing(item); + playerInbox->internalAddThing(item); item->startDecaying(); } else { - ItemsMap::const_iterator it2 = inboxItems.find(pid); - if (it2 == inboxItems.end()) { + auto inboxIt = inboxItems.find(pid); + if (inboxIt == inboxItems.end()) { continue; } - std::shared_ptr<Container> container = it2->second.first->getContainer(); + const std::shared_ptr<Container> &container = inboxIt->second.first->getContainer(); if (container) { container->internalAddThing(item); itemsToStartDecaying.emplace_back(item); @@ -668,7 +717,7 @@ void IOLoginDataLoad::loadPlayerInboxItems(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerStorageMap(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerStorageMap(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -684,7 +733,7 @@ void IOLoginDataLoad::loadPlayerStorageMap(std::shared_ptr<Player> player, DBRes } } -void IOLoginDataLoad::loadPlayerVip(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerVip(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -722,7 +771,7 @@ void IOLoginDataLoad::loadPlayerVip(std::shared_ptr<Player> player, DBResult_ptr } } -void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerPreyClass(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -769,7 +818,7 @@ void IOLoginDataLoad::loadPlayerPreyClass(std::shared_ptr<Player> player, DBResu } } -void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerTaskHuntingClass(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -819,7 +868,7 @@ void IOLoginDataLoad::loadPlayerTaskHuntingClass(std::shared_ptr<Player> player, } } -void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerForgeHistory(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result || !player) { g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__); return; @@ -840,7 +889,7 @@ void IOLoginDataLoad::loadPlayerForgeHistory(std::shared_ptr<Player> player, DBR } } -void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr<Player> player, DBResult_ptr result) { +void IOLoginDataLoad::loadPlayerBosstiary(const std::shared_ptr<Player> &player, DBResult_ptr result) { if (!result) { g_logger().warn("[{}] - Result nullptr", __FUNCTION__); return; @@ -877,7 +926,7 @@ void IOLoginDataLoad::loadPlayerBosstiary(std::shared_ptr<Player> player, DBResu } } -void IOLoginDataLoad::bindRewardBag(std::shared_ptr<Player> player, ItemsMap &rewardItemsMap) { +void IOLoginDataLoad::bindRewardBag(const std::shared_ptr<Player> &player, ItemsMap &rewardItemsMap) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; @@ -899,25 +948,29 @@ void IOLoginDataLoad::bindRewardBag(std::shared_ptr<Player> player, ItemsMap &re void IOLoginDataLoad::insertItemsIntoRewardBag(const ItemsMap &rewardItemsMap) { for (const auto &it : std::views::reverse(rewardItemsMap)) { const std::pair<std::shared_ptr<Item>, int32_t> &pair = it.second; - std::shared_ptr<Item> item = pair.first; + const auto &item = pair.first; + if (!item) { + continue; + } + int32_t pid = pair.second; if (pid == 0) { break; } - ItemsMap::const_iterator it2 = rewardItemsMap.find(pid); - if (it2 == rewardItemsMap.end()) { + auto rewardIt = rewardItemsMap.find(pid); + if (rewardIt == rewardItemsMap.end()) { continue; } - std::shared_ptr<Container> container = it2->second.first->getContainer(); + const std::shared_ptr<Container> &container = rewardIt->second.first->getContainer(); if (container) { container->internalAddThing(item); } } } -void IOLoginDataLoad::loadPlayerInitializeSystem(std::shared_ptr<Player> player) { +void IOLoginDataLoad::loadPlayerInitializeSystem(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; @@ -936,7 +989,7 @@ void IOLoginDataLoad::loadPlayerInitializeSystem(std::shared_ptr<Player> player) player->initializeTaskHunting(); } -void IOLoginDataLoad::loadPlayerUpdateSystem(std::shared_ptr<Player> player) { +void IOLoginDataLoad::loadPlayerUpdateSystem(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[{}] - Player nullptr", __FUNCTION__); return; diff --git a/src/io/functions/iologindata_load_player.hpp b/src/io/functions/iologindata_load_player.hpp index e67faf4d8c1..ca05bdcb1b8 100644 --- a/src/io/functions/iologindata_load_player.hpp +++ b/src/io/functions/iologindata_load_player.hpp @@ -11,40 +11,44 @@ #include "io/iologindata.hpp" +class Player; +class DBResult; +using DBResult_ptr = std::shared_ptr<DBResult>; + class IOLoginDataLoad : public IOLoginData { public: - static bool loadPlayerBasicInfo(std::shared_ptr<Player> player, DBResult_ptr result); - static bool preLoadPlayer(std::shared_ptr<Player> player, const std::string &name); - static void loadPlayerExperience(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerBlessings(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerConditions(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerDefaultOutfit(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerSkullSystem(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerSkill(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerKills(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerGuild(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerStashItems(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerBestiaryCharms(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerInstantSpellList(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerInventoryItems(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerStoreInbox(std::shared_ptr<Player> player); - static void loadPlayerDepotItems(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadRewardItems(std::shared_ptr<Player> player); - static void loadPlayerInboxItems(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerStorageMap(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerVip(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerPreyClass(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerTaskHuntingClass(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerForgeHistory(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerBosstiary(std::shared_ptr<Player> player, DBResult_ptr result); - static void loadPlayerInitializeSystem(std::shared_ptr<Player> player); - static void loadPlayerUpdateSystem(std::shared_ptr<Player> player); + static bool loadPlayerBasicInfo(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static bool preLoadPlayer(const std::shared_ptr<Player> &player, const std::string &name); + static void loadPlayerExperience(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerBlessings(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerConditions(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerDefaultOutfit(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerSkullSystem(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerSkill(const std::shared_ptr<Player> &player, const DBResult_ptr &result); + static void loadPlayerKills(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerGuild(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerStashItems(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerBestiaryCharms(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerInstantSpellList(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerInventoryItems(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerStoreInbox(const std::shared_ptr<Player> &player); + static void loadPlayerDepotItems(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadRewardItems(const std::shared_ptr<Player> &player); + static void loadPlayerInboxItems(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerStorageMap(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerVip(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerPreyClass(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerTaskHuntingClass(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerForgeHistory(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerBosstiary(const std::shared_ptr<Player> &player, DBResult_ptr result); + static void loadPlayerInitializeSystem(const std::shared_ptr<Player> &player); + static void loadPlayerUpdateSystem(const std::shared_ptr<Player> &player); private: using ItemsMap = std::map<uint32_t, std::pair<std::shared_ptr<Item>, uint32_t>>; - static void bindRewardBag(std::shared_ptr<Player> player, ItemsMap &rewardItemsMap); + static void bindRewardBag(const std::shared_ptr<Player> &player, ItemsMap &rewardItemsMap); static void insertItemsIntoRewardBag(const ItemsMap &rewardItemsMap); - static void loadItems(ItemsMap &itemsMap, DBResult_ptr result, const std::shared_ptr<Player> &player); + static void loadItems(ItemsMap &itemsMap, const DBResult_ptr &result, const std::shared_ptr<Player> &player); }; diff --git a/src/io/functions/iologindata_save_player.cpp b/src/io/functions/iologindata_save_player.cpp index ec8ab71fd07..613fdac1cb0 100644 --- a/src/io/functions/iologindata_save_player.cpp +++ b/src/io/functions/iologindata_save_player.cpp @@ -8,9 +8,18 @@ */ #include "io/functions/iologindata_save_player.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/monsters/monsters.hpp" #include "game/game.hpp" +#include "io/ioprey.hpp" +#include "items/containers/depot/depotchest.hpp" +#include "items/containers/inbox/inbox.hpp" +#include "items/containers/rewards/reward.hpp" +#include "creatures/players/player.hpp" -bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockList &itemList, DBInsert &query_insert, PropWriteStream &propWriteStream) { +bool IOLoginDataSave::saveItems(const std::shared_ptr<Player> &player, const ItemBlockList &itemList, DBInsert &query_insert, PropWriteStream &propWriteStream) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -25,16 +34,21 @@ bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockL int32_t runningId = 100; // Loop through each item in itemList - const auto openContainers = player->getOpenContainers(); + const auto &openContainers = player->getOpenContainers(); for (const auto &it : itemList) { + const auto &item = it.second; + if (!item) { + continue; + } + int32_t pid = it.first; - std::shared_ptr<Item> item = it.second; + ++runningId; // Update container attributes if necessary - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const std::shared_ptr<Container> &container = item->getContainer()) { if (!container) { - continue; // Check for null container + continue; } if (container->getAttribute<int64_t>(ItemAttribute_t::OPENCONTAINER) > 0) { @@ -58,13 +72,8 @@ bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockL } // Serialize item attributes - try { - propWriteStream.clear(); - item->serializeAttr(propWriteStream); - } catch (...) { - g_logger().error("Error serializing item attributes."); - return false; - } + propWriteStream.clear(); + item->serializeAttr(propWriteStream); size_t attributesSize; const char* attributes = propWriteStream.getStream(attributesSize); @@ -80,17 +89,17 @@ bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockL // Loop through containers in queue while (!queue.empty()) { const ContainerBlock &cb = queue.front(); - std::shared_ptr<Container> container = cb.first; - int32_t parentId = cb.second; - + const std::shared_ptr<Container> &container = cb.first; if (!container) { - continue; // Check for null container + continue; } + int32_t parentId = cb.second; + // Loop through items in container for (auto &item : container->getItemList()) { if (!item) { - continue; // Check for null item + continue; } ++runningId; @@ -117,14 +126,8 @@ bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockL } // Serialize item attributes - try { - propWriteStream.clear(); - item->serializeAttr(propWriteStream); - item->stopDecaying(); - } catch (...) { - g_logger().error("Error serializing item attributes in container."); - return false; - } + propWriteStream.clear(); + item->serializeAttr(propWriteStream); size_t attributesSize; const char* attributes = propWriteStream.getStream(attributesSize); @@ -149,7 +152,7 @@ bool IOLoginDataSave::saveItems(std::shared_ptr<Player> player, const ItemBlockL return true; } -bool IOLoginDataSave::savePlayerFirst(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerFirst(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -202,7 +205,9 @@ bool IOLoginDataSave::savePlayerFirst(std::shared_ptr<Player> player) { query << "`manamax` = " << player->manaMax << ","; query << "`manaspent` = " << player->manaSpent << ","; query << "`soul` = " << static_cast<uint16_t>(player->soul) << ","; - query << "`town_id` = " << player->town->getID() << ","; + if (player->town) { + query << "`town_id` = " << player->town->getID() << ","; + } const Position &loginPosition = player->getLoginPosition(); query << "`posx` = " << loginPosition.getX() << ","; @@ -315,7 +320,7 @@ bool IOLoginDataSave::savePlayerFirst(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerStash(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerStash(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -344,7 +349,7 @@ bool IOLoginDataSave::savePlayerStash(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerSpells(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerSpells(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -373,7 +378,7 @@ bool IOLoginDataSave::savePlayerSpells(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerKills(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerKills(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -402,7 +407,7 @@ bool IOLoginDataSave::savePlayerKills(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerBestiarySystem(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerBestiarySystem(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -452,7 +457,7 @@ bool IOLoginDataSave::savePlayerBestiarySystem(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerItem(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerItem(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -471,7 +476,7 @@ bool IOLoginDataSave::savePlayerItem(std::shared_ptr<Player> player) { ItemBlockList itemList; for (int32_t slotId = CONST_SLOT_FIRST; slotId <= CONST_SLOT_LAST; ++slotId) { - std::shared_ptr<Item> item = player->inventory[slotId]; + const auto &item = player->inventory[slotId]; if (item) { itemList.emplace_back(slotId, item); } @@ -484,7 +489,7 @@ bool IOLoginDataSave::savePlayerItem(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerDepotItems(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerDepotItems(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -506,7 +511,7 @@ bool IOLoginDataSave::savePlayerDepotItems(std::shared_ptr<Player> player) { DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES "); for (const auto &[pid, depotChest] : player->depotChests) { - for (std::shared_ptr<Item> item : depotChest->getItemList()) { + for (const std::shared_ptr<Item> &item : depotChest->getItemList()) { depotList.emplace_back(pid, item); } } @@ -519,7 +524,7 @@ bool IOLoginDataSave::savePlayerDepotItems(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::saveRewardItems(std::shared_ptr<Player> player) { +bool IOLoginDataSave::saveRewardItems(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -553,7 +558,7 @@ bool IOLoginDataSave::saveRewardItems(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerInbox(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerInbox(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -581,7 +586,7 @@ bool IOLoginDataSave::savePlayerInbox(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerPreyClass(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerPreyClass(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -635,7 +640,7 @@ bool IOLoginDataSave::savePlayerPreyClass(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerTaskHuntingClass(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerTaskHuntingClass(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -687,7 +692,7 @@ bool IOLoginDataSave::savePlayerTaskHuntingClass(std::shared_ptr<Player> player) return true; } -bool IOLoginDataSave::savePlayerForgeHistory(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerForgeHistory(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -721,7 +726,7 @@ bool IOLoginDataSave::savePlayerForgeHistory(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerBosstiary(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerBosstiary(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; @@ -765,7 +770,7 @@ bool IOLoginDataSave::savePlayerBosstiary(std::shared_ptr<Player> player) { return true; } -bool IOLoginDataSave::savePlayerStorage(std::shared_ptr<Player> player) { +bool IOLoginDataSave::savePlayerStorage(const std::shared_ptr<Player> &player) { if (!player) { g_logger().warn("[IOLoginData::savePlayer] - Player nullptr: {}", __FUNCTION__); return false; diff --git a/src/io/functions/iologindata_save_player.hpp b/src/io/functions/iologindata_save_player.hpp index bbd44105de6..1f871a3b5db 100644 --- a/src/io/functions/iologindata_save_player.hpp +++ b/src/io/functions/iologindata_save_player.hpp @@ -11,22 +11,25 @@ #include "io/iologindata.hpp" +class PropWriteStream; +class DBInsert; + class IOLoginDataSave : public IOLoginData { public: - static bool savePlayerFirst(std::shared_ptr<Player> player); - static bool savePlayerStash(std::shared_ptr<Player> player); - static bool savePlayerSpells(std::shared_ptr<Player> player); - static bool savePlayerKills(std::shared_ptr<Player> player); - static bool savePlayerBestiarySystem(std::shared_ptr<Player> player); - static bool savePlayerItem(std::shared_ptr<Player> player); - static bool savePlayerDepotItems(std::shared_ptr<Player> player); - static bool saveRewardItems(std::shared_ptr<Player> player); - static bool savePlayerInbox(std::shared_ptr<Player> player); - static bool savePlayerPreyClass(std::shared_ptr<Player> player); - static bool savePlayerTaskHuntingClass(std::shared_ptr<Player> player); - static bool savePlayerForgeHistory(std::shared_ptr<Player> player); - static bool savePlayerBosstiary(std::shared_ptr<Player> player); - static bool savePlayerStorage(std::shared_ptr<Player> player); + static bool savePlayerFirst(const std::shared_ptr<Player> &player); + static bool savePlayerStash(const std::shared_ptr<Player> &player); + static bool savePlayerSpells(const std::shared_ptr<Player> &player); + static bool savePlayerKills(const std::shared_ptr<Player> &player); + static bool savePlayerBestiarySystem(const std::shared_ptr<Player> &player); + static bool savePlayerItem(const std::shared_ptr<Player> &player); + static bool savePlayerDepotItems(const std::shared_ptr<Player> &player); + static bool saveRewardItems(const std::shared_ptr<Player> &player); + static bool savePlayerInbox(const std::shared_ptr<Player> &player); + static bool savePlayerPreyClass(const std::shared_ptr<Player> &player); + static bool savePlayerTaskHuntingClass(const std::shared_ptr<Player> &player); + static bool savePlayerForgeHistory(const std::shared_ptr<Player> &player); + static bool savePlayerBosstiary(const std::shared_ptr<Player> &player); + static bool savePlayerStorage(const std::shared_ptr<Player> &player); protected: using ItemBlockList = std::list<std::pair<int32_t, std::shared_ptr<Item>>>; @@ -34,5 +37,5 @@ class IOLoginDataSave : public IOLoginData { using ItemRewardList = std::list<std::pair<int32_t, std::shared_ptr<Item>>>; using ItemInboxList = std::list<std::pair<int32_t, std::shared_ptr<Item>>>; - static bool saveItems(std::shared_ptr<Player> player, const ItemBlockList &itemList, DBInsert &query_insert, PropWriteStream &stream); + static bool saveItems(const std::shared_ptr<Player> &player, const ItemBlockList &itemList, DBInsert &query_insert, PropWriteStream &stream); }; diff --git a/src/io/io_bosstiary.cpp b/src/io/io_bosstiary.cpp index d10aed53615..3e8a05524e6 100644 --- a/src/io/io_bosstiary.cpp +++ b/src/io/io_bosstiary.cpp @@ -12,8 +12,12 @@ #include "creatures/monsters/monsters.hpp" #include "creatures/players/player.hpp" #include "game/game.hpp" +#include "lib/di/container.hpp" #include "utils/tools.hpp" -#include "items/item.hpp" + +IOBosstiary &IOBosstiary::getInstance() { + return inject<IOBosstiary>(); +} void IOBosstiary::loadBoostedBoss() { Database &database = Database::getInstance(); @@ -25,7 +29,7 @@ void IOBosstiary::loadBoostedBoss() { return; } - uint16_t date = result->getNumber<uint16_t>("date"); + auto date = result->getNumber<uint16_t>("date"); auto timeNow = getTimeNow(); auto time = localtime(&timeNow); auto today = time->tm_mday; @@ -59,12 +63,12 @@ void IOBosstiary::loadBoostedBoss() { } // Check if not have archfoe registered boss - if (bossInfo.size() == 0) { + if (bossInfo.empty()) { g_logger().error("Failed to boost a boss. There is no boss registered with the Archfoe Rarity."); return; } - uint16_t oldBossRace = result->getNumber<uint16_t>("raceid"); + auto oldBossRace = result->getNumber<uint16_t>("raceid"); while (true) { uint32_t randomIndex = uniform_random(0, static_cast<int32_t>(bossInfo.size())); auto it = std::next(bossInfo.begin(), randomIndex); @@ -167,7 +171,7 @@ std::shared_ptr<MonsterType> IOBosstiary::getMonsterTypeByBossRaceId(uint16_t ra return nullptr; } -void IOBosstiary::addBosstiaryKill(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype, uint32_t amount /*= 1*/) const { +void IOBosstiary::addBosstiaryKill(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype, uint32_t amount /*= 1*/) const { if (!player || !mtype) { return; } @@ -267,7 +271,7 @@ std::vector<uint16_t> IOBosstiary::getBosstiaryFinished(const std::shared_ptr<Pl return unlockedMonsters.data(); } -uint8_t IOBosstiary::getBossCurrentLevel(std::shared_ptr<Player> player, uint16_t bossId) const { +uint8_t IOBosstiary::getBossCurrentLevel(const std::shared_ptr<Player> &player, uint16_t bossId) const { if (bossId == 0 || !player) { return 0; } diff --git a/src/io/io_bosstiary.hpp b/src/io/io_bosstiary.hpp index 11eabf30a8b..92a8bf0b624 100644 --- a/src/io/io_bosstiary.hpp +++ b/src/io/io_bosstiary.hpp @@ -9,11 +9,6 @@ #pragma once -#include <map> -#include <string> -#include <vector> -#include "lib/di/container.hpp" - enum class BosstiaryRarity_t : uint8_t { RARITY_BANE = 0, RARITY_ARCHFOE = 1, @@ -39,9 +34,7 @@ class IOBosstiary { IOBosstiary(const IOBosstiary &) = delete; void operator=(const IOBosstiary &) = delete; - static IOBosstiary &getInstance() { - return inject<IOBosstiary>(); - } + static IOBosstiary &getInstance(); void loadBoostedBoss(); @@ -60,11 +53,11 @@ class IOBosstiary { uint16_t getBoostedBossId() const; std::shared_ptr<MonsterType> getMonsterTypeByBossRaceId(uint16_t raceId) const; - void addBosstiaryKill(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype, uint32_t amount = 1) const; + void addBosstiaryKill(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype, uint32_t amount = 1) const; uint16_t calculateLootBonus(uint32_t bossPoints) const; uint32_t calculateBossPoints(uint16_t lootBonus) const; std::vector<uint16_t> getBosstiaryFinished(const std::shared_ptr<Player> &player, uint8_t level = 1) const; - uint8_t getBossCurrentLevel(std::shared_ptr<Player> player, uint16_t bossId) const; + uint8_t getBossCurrentLevel(const std::shared_ptr<Player> &player, uint16_t bossId) const; uint32_t calculteRemoveBoss(uint8_t removeTimes) const; const std::vector<LevelInfo> &getBossRaceKillStages(BosstiaryRarity_t race) const; diff --git a/src/io/io_wheel.cpp b/src/io/io_wheel.cpp index 72d5e207d4c..cfcf6593010 100644 --- a/src/io/io_wheel.cpp +++ b/src/io/io_wheel.cpp @@ -58,7 +58,7 @@ namespace InternalPlayerWheel { return; } - auto spell = g_spells().getInstantSpellByName(name); + const auto &spell = g_spells().getInstantSpellByName(name); if (spell) { g_logger().trace("[{}] registering instant spell with name {}", __FUNCTION__, spell->getName()); // Increase data @@ -127,7 +127,7 @@ bool IOWheel::initializeGlobalData(bool reload /* = false*/) { // Register spells for druid for (const auto &data : getWheelBonusData().spells.druid) { for (size_t i = 1; i < 3; ++i) { - const auto grade = data.grade[i]; + const auto &grade = data.grade[i]; InternalPlayerWheel::registerWheelSpellTable(grade, data.name, static_cast<WheelSpellGrade_t>(i)); } } @@ -181,7 +181,7 @@ const VocationBonusMap &IOWheel::getWheelMapFunctions() const { std::pair<int, int> IOWheel::getRevelationStatByStage(WheelStageEnum_t stageType) const { // Let's remove one, because the std::array starts with 0 and the stages with 1 - auto array = m_wheelBonusData.revelation.stats[static_cast<uint8_t>(stageType) - 1]; + const auto &array = m_wheelBonusData.revelation.stats[static_cast<uint8_t>(stageType) - 1]; return std::make_pair(array.damage, array.healing); } @@ -222,32 +222,32 @@ void IOWheel::initializeMapData() { void IOWheel::initializeDruidSpells() { m_wheelBonusData.spells.druid[0].name = "Strong Ice Wave"; m_wheelBonusData.spells.druid[0].grade[1].leech.mana = 3; - m_wheelBonusData.spells.druid[0].grade[2].increase.damage = 30; + m_wheelBonusData.spells.druid[0].grade[2].increase.damage = 10; m_wheelBonusData.spells.druid[1].name = "Mass Healing"; - m_wheelBonusData.spells.druid[1].grade[1].increase.heal = 10; + m_wheelBonusData.spells.druid[1].grade[1].increase.heal = 4; m_wheelBonusData.spells.druid[1].grade[2].increase.area = true; m_wheelBonusData.spells.druid[2].name = "Nature's Embrace"; - m_wheelBonusData.spells.druid[2].grade[1].increase.heal = 10; + m_wheelBonusData.spells.druid[2].grade[1].increase.heal = 11; m_wheelBonusData.spells.druid[2].grade[2].decrease.cooldown = 10; m_wheelBonusData.spells.druid[3].name = "Terra Wave"; - m_wheelBonusData.spells.druid[3].grade[1].increase.damage = 25; + m_wheelBonusData.spells.druid[3].grade[1].increase.damage = static_cast<int>(std::round(6.5)); m_wheelBonusData.spells.druid[3].grade[2].leech.life = 5; m_wheelBonusData.spells.druid[4].name = "Heal Friend"; m_wheelBonusData.spells.druid[4].grade[1].decrease.manaCost = 10; - m_wheelBonusData.spells.druid[4].grade[2].increase.heal = 10; + m_wheelBonusData.spells.druid[4].grade[2].increase.heal = static_cast<int>(std::round(5.5)); } void IOWheel::initializeKnightSpells() { m_wheelBonusData.spells.knight[0].name = "Front Sweep"; m_wheelBonusData.spells.knight[0].grade[1].leech.life = 5; - m_wheelBonusData.spells.knight[0].grade[2].increase.damage = 30; + m_wheelBonusData.spells.knight[0].grade[2].increase.damage = 14; m_wheelBonusData.spells.knight[1].name = "Groundshaker"; - m_wheelBonusData.spells.knight[1].grade[1].increase.damage = 25; + m_wheelBonusData.spells.knight[1].grade[1].increase.damage = static_cast<int>(std::round(12.5)); m_wheelBonusData.spells.knight[1].grade[2].decrease.cooldown = 2; m_wheelBonusData.spells.knight[2].name = "Chivalrous Challenge"; @@ -255,12 +255,12 @@ void IOWheel::initializeKnightSpells() { m_wheelBonusData.spells.knight[2].grade[2].increase.aditionalTarget = 1; m_wheelBonusData.spells.knight[3].name = "Intense Wound Cleansing"; - m_wheelBonusData.spells.knight[3].grade[1].increase.heal = 10; + m_wheelBonusData.spells.knight[3].grade[1].increase.heal = 125; m_wheelBonusData.spells.knight[3].grade[2].decrease.cooldown = 300; m_wheelBonusData.spells.knight[4].name = "Fierce Berserk"; m_wheelBonusData.spells.knight[4].grade[1].decrease.manaCost = 30; - m_wheelBonusData.spells.knight[4].grade[2].increase.damage = 25; + m_wheelBonusData.spells.knight[4].grade[2].increase.damage = 10; } void IOWheel::initializePaladinSpells() { @@ -270,7 +270,7 @@ void IOWheel::initializePaladinSpells() { m_wheelBonusData.spells.paladin[1].name = "Strong Ethereal Spear"; m_wheelBonusData.spells.paladin[1].grade[1].decrease.cooldown = 2; - m_wheelBonusData.spells.paladin[1].grade[2].increase.damage = 25; + m_wheelBonusData.spells.paladin[1].grade[2].increase.damage = 380; m_wheelBonusData.spells.paladin[2].name = "Divine Dazzle"; m_wheelBonusData.spells.paladin[2].grade[1].increase.aditionalTarget = 1; @@ -283,7 +283,7 @@ void IOWheel::initializePaladinSpells() { m_wheelBonusData.spells.paladin[4].name = "Divine Caldera"; m_wheelBonusData.spells.paladin[4].grade[1].decrease.manaCost = 20; - m_wheelBonusData.spells.paladin[4].grade[2].increase.damage = 25; + m_wheelBonusData.spells.paladin[4].grade[2].increase.damage = static_cast<int>(std::round(8.5)); } void IOWheel::initializeSorcererSpells() { @@ -292,19 +292,19 @@ void IOWheel::initializeSorcererSpells() { m_wheelBonusData.spells.sorcerer[1].name = "Sap Strength"; m_wheelBonusData.spells.sorcerer[1].grade[1].increase.area = true; - m_wheelBonusData.spells.sorcerer[1].grade[2].increase.damageReduction = 10; + m_wheelBonusData.spells.sorcerer[1].grade[2].increase.damageReduction = 1; m_wheelBonusData.spells.sorcerer[2].name = "Energy Wave"; - m_wheelBonusData.spells.sorcerer[2].grade[1].increase.damage = 25; + m_wheelBonusData.spells.sorcerer[2].grade[1].increase.damage = 5; m_wheelBonusData.spells.sorcerer[2].grade[2].increase.area = true; m_wheelBonusData.spells.sorcerer[3].name = "Great Fire Wave"; m_wheelBonusData.spells.sorcerer[3].grade[1].increase.criticalDamage = 15; m_wheelBonusData.spells.sorcerer[3].grade[1].increase.criticalChance = 10; - m_wheelBonusData.spells.sorcerer[3].grade[2].increase.damage = 25; + m_wheelBonusData.spells.sorcerer[3].grade[2].increase.damage = 5; m_wheelBonusData.spells.sorcerer[4].name = "Any_Focus_Mage_Spell"; - m_wheelBonusData.spells.sorcerer[4].grade[1].increase.damage = 25; + m_wheelBonusData.spells.sorcerer[4].grade[1].increase.damage = 5; m_wheelBonusData.spells.sorcerer[4].grade[2].decrease.cooldown = 4; m_wheelBonusData.spells.sorcerer[4].grade[2].decrease.secondaryGroupCooldown = 4; } @@ -399,7 +399,7 @@ void IOWheel::slotGreen200(const std::shared_ptr<Player> &player, uint16_t point bonusData.stats.health += 2 * points; bonusData.stats.mana += 3 * points; if (pointsInSlot) { - bonusData.instant.positionalTatics = true; + bonusData.instant.positionalTactics = true; } } else { bonusData.stats.health += 1 * points; diff --git a/src/io/iobestiary.cpp b/src/io/iobestiary.cpp index 83dd2ed806e..b18ed181467 100644 --- a/src/io/iobestiary.cpp +++ b/src/io/iobestiary.cpp @@ -7,16 +7,18 @@ * Website: https://docs.opentibiabr.com/ */ -#include "declarations.hpp" -#include "game/game.hpp" #include "io/iobestiary.hpp" + +#include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" #include "creatures/monsters/monsters.hpp" #include "creatures/players/player.hpp" +#include "game/game.hpp" #include "lib/metrics/metrics.hpp" SoftSingleton IOBestiary::instanceTracker("IOBestiary"); -bool IOBestiary::parseCharmCombat(const std::shared_ptr<Charm> charm, std::shared_ptr<Player> player, std::shared_ptr<Creature> target, int32_t realDamage, bool dueToPotion, bool checkArmor) { +bool IOBestiary::parseCharmCombat(const std::shared_ptr<Charm> &charm, const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, int32_t realDamage, bool dueToPotion, bool checkArmor) { if (!charm || !player || !target) { return false; } @@ -93,6 +95,10 @@ bool IOBestiary::parseCharmCombat(const std::shared_ptr<Charm> charm, std::share return false; } +IOBestiary &IOBestiary::getInstance() { + return inject<IOBestiary>(); +} + std::shared_ptr<Charm> IOBestiary::getBestiaryCharm(charmRune_t activeCharm, bool force /*= false*/) const { const auto charmInternal = g_game().getCharmList(); for (const auto &tmpCharm : charmInternal) { @@ -113,7 +119,7 @@ std::shared_ptr<Charm> IOBestiary::getBestiaryCharm(charmRune_t activeCharm, boo } std::map<uint16_t, std::string> IOBestiary::findRaceByName(const std::string &race, bool Onlystring /*= true*/, BestiaryType_t raceNumber /*= BESTY_RACE_NONE*/) const { - std::map<uint16_t, std::string> best_list = g_game().getBestiaryList(); + const std::map<uint16_t, std::string> &best_list = g_game().getBestiaryList(); std::map<uint16_t, std::string> race_list; if (Onlystring) { @@ -134,7 +140,7 @@ std::map<uint16_t, std::string> IOBestiary::findRaceByName(const std::string &ra return race_list; } -uint8_t IOBestiary::getKillStatus(const std::shared_ptr<MonsterType> mtype, uint32_t killAmount) const { +uint8_t IOBestiary::getKillStatus(const std::shared_ptr<MonsterType> &mtype, uint32_t killAmount) const { if (killAmount < mtype->info.bestiaryFirstUnlock) { return 1; } else if (killAmount < mtype->info.bestiarySecondUnlock) { @@ -145,7 +151,7 @@ uint8_t IOBestiary::getKillStatus(const std::shared_ptr<MonsterType> mtype, uint return 4; } -void IOBestiary::resetCharmRuneCreature(std::shared_ptr<Player> player, const std::shared_ptr<Charm> charm) { +void IOBestiary::resetCharmRuneCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Charm> &charm) const { if (!player || !charm) { return; } @@ -155,7 +161,7 @@ void IOBestiary::resetCharmRuneCreature(std::shared_ptr<Player> player, const st player->parseRacebyCharm(charm->id, true, 0); } -void IOBestiary::setCharmRuneCreature(std::shared_ptr<Player> player, const std::shared_ptr<Charm> charm, uint16_t raceid) { +void IOBestiary::setCharmRuneCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Charm> &charm, uint16_t raceid) const { if (!player || !charm) { return; } @@ -165,14 +171,14 @@ void IOBestiary::setCharmRuneCreature(std::shared_ptr<Player> player, const std: player->setUsedRunesBit(Toggle); } -std::list<charmRune_t> IOBestiary::getCharmUsedRuneBitAll(std::shared_ptr<Player> player) { +std::list<charmRune_t> IOBestiary::getCharmUsedRuneBitAll(const std::shared_ptr<Player> &player) { int32_t input = player->getUsedRunesBit(); int8_t i = 0; std::list<charmRune_t> rtn; while (input != 0) { if ((input & 1) == 1) { - charmRune_t tmpcharm = static_cast<charmRune_t>(i); + auto tmpcharm = static_cast<charmRune_t>(i); rtn.push_front(tmpcharm); } input = input >> 1; @@ -181,7 +187,7 @@ std::list<charmRune_t> IOBestiary::getCharmUsedRuneBitAll(std::shared_ptr<Player return rtn; } -uint16_t IOBestiary::getBestiaryRaceUnlocked(std::shared_ptr<Player> player, BestiaryType_t race) const { +uint16_t IOBestiary::getBestiaryRaceUnlocked(const std::shared_ptr<Player> &player, BestiaryType_t race) const { if (!player) { return 0; } @@ -198,7 +204,7 @@ uint16_t IOBestiary::getBestiaryRaceUnlocked(std::shared_ptr<Player> player, Bes return count; } -void IOBestiary::addCharmPoints(std::shared_ptr<Player> player, uint16_t amount, bool negative /*= false*/) { +void IOBestiary::addCharmPoints(const std::shared_ptr<Player> &player, uint16_t amount, bool negative /*= false*/) { if (!player) { return; } @@ -212,7 +218,7 @@ void IOBestiary::addCharmPoints(std::shared_ptr<Player> player, uint16_t amount, player->setCharmPoints(myCharms); } -void IOBestiary::addBestiaryKill(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype, uint32_t amount /*= 1*/) { +void IOBestiary::addBestiaryKill(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype, uint32_t amount /*= 1*/) { uint16_t raceid = mtype->info.raceid; if (raceid == 0 || !player || !mtype) { return; @@ -239,7 +245,7 @@ void IOBestiary::addBestiaryKill(std::shared_ptr<Player> player, const std::shar player->refreshCyclopediaMonsterTracker(); } -charmRune_t IOBestiary::getCharmFromTarget(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype) { +charmRune_t IOBestiary::getCharmFromTarget(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype) { if (!player || !mtype) { return CHARM_NONE; } @@ -256,7 +262,7 @@ charmRune_t IOBestiary::getCharmFromTarget(std::shared_ptr<Player> player, const return CHARM_NONE; } -bool IOBestiary::hasCharmUnlockedRuneBit(const std::shared_ptr<Charm> charm, int32_t input) const { +bool IOBestiary::hasCharmUnlockedRuneBit(const std::shared_ptr<Charm> &charm, int32_t input) const { if (!charm) { return false; } @@ -264,7 +270,7 @@ bool IOBestiary::hasCharmUnlockedRuneBit(const std::shared_ptr<Charm> charm, int return ((input & charm->binary) != 0); } -int32_t IOBestiary::bitToggle(int32_t input, const std::shared_ptr<Charm> charm, bool on) const { +int32_t IOBestiary::bitToggle(int32_t input, const std::shared_ptr<Charm> &charm, bool on) const { if (!charm) { return CHARM_NONE; } @@ -281,7 +287,7 @@ int32_t IOBestiary::bitToggle(int32_t input, const std::shared_ptr<Charm> charm, } } -void IOBestiary::sendBuyCharmRune(std::shared_ptr<Player> player, charmRune_t runeID, uint8_t action, uint16_t raceid) { +void IOBestiary::sendBuyCharmRune(const std::shared_ptr<Player> &player, charmRune_t runeID, uint8_t action, uint16_t raceid) { const auto charm = getBestiaryCharm(runeID); if (!player || !charm) { return; @@ -343,7 +349,7 @@ void IOBestiary::sendBuyCharmRune(std::shared_ptr<Player> player, charmRune_t ru player->BestiarysendCharms(); } -std::map<uint8_t, int16_t> IOBestiary::getMonsterElements(const std::shared_ptr<MonsterType> mtype) const { +std::map<uint8_t, int16_t> IOBestiary::getMonsterElements(const std::shared_ptr<MonsterType> &mtype) const { std::map<uint8_t, int16_t> defaultMap = {}; for (uint8_t i = 0; i <= 7; i++) { defaultMap[i] = 100; @@ -381,7 +387,7 @@ std::map<uint8_t, int16_t> IOBestiary::getMonsterElements(const std::shared_ptr< return defaultMap; } -std::map<uint16_t, uint32_t> IOBestiary::getBestiaryKillCountByMonsterIDs(std::shared_ptr<Player> player, std::map<uint16_t, std::string> mtype_list) const { +std::map<uint16_t, uint32_t> IOBestiary::getBestiaryKillCountByMonsterIDs(const std::shared_ptr<Player> &player, const std::map<uint16_t, std::string> &mtype_list) const { std::map<uint16_t, uint32_t> raceMonsters = {}; for (const auto &it : mtype_list) { uint16_t raceid = it.first; diff --git a/src/io/iobestiary.hpp b/src/io/iobestiary.hpp index a521ce68852..4eb576327fe 100644 --- a/src/io/iobestiary.hpp +++ b/src/io/iobestiary.hpp @@ -9,12 +9,16 @@ #pragma once -#include "declarations.hpp" #include "lib/di/soft_singleton.hpp" -#include "lua/scripts/luascript.hpp" -#include "creatures/players/player.hpp" +#include "creatures/creatures_definitions.hpp" + +class Player; class Game; +class SoftSingleton; +class SoftSingletonGuard; +class MonsterType; +class Creature; class Charm { public: @@ -26,14 +30,14 @@ class Charm { std::string name; charmRune_t id = CHARM_NONE; std::string description; - charm_t type; + charm_t type {}; uint16_t points = 0; int32_t binary = 0; std::string cancelMsg; std::string logMsg; CombatType_t dmgtype = COMBAT_NONE; - uint16_t effect = CONST_ME_NONE; + uint16_t effect = 0; SoundEffect_t soundImpactEffect = SoundEffect_t::SILENCE; SoundEffect_t soundCastEffect = SoundEffect_t::SILENCE; @@ -50,34 +54,32 @@ class IOBestiary { IOBestiary(const IOBestiary &) = delete; void operator=(const IOBestiary &) = delete; - static IOBestiary &getInstance() { - return inject<IOBestiary>(); - } + static IOBestiary &getInstance(); std::shared_ptr<Charm> getBestiaryCharm(charmRune_t activeCharm, bool force = false) const; - void addBestiaryKill(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype, uint32_t amount = 1); - bool parseCharmCombat(const std::shared_ptr<Charm> charm, std::shared_ptr<Player> player, std::shared_ptr<Creature> target, int32_t realDamage, bool dueToPotion = false, bool checkArmor = false); - void addCharmPoints(std::shared_ptr<Player> player, uint16_t amount, bool negative = false); - void sendBuyCharmRune(std::shared_ptr<Player> player, charmRune_t runeID, uint8_t action, uint16_t raceid); - void setCharmRuneCreature(std::shared_ptr<Player> player, const std::shared_ptr<Charm> charm, uint16_t raceid); - void resetCharmRuneCreature(std::shared_ptr<Player> player, const std::shared_ptr<Charm> charm); + void addBestiaryKill(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype, uint32_t amount = 1); + bool parseCharmCombat(const std::shared_ptr<Charm> &charm, const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, int32_t realDamage, bool dueToPotion = false, bool checkArmor = false); + void addCharmPoints(const std::shared_ptr<Player> &player, uint16_t amount, bool negative = false); + void sendBuyCharmRune(const std::shared_ptr<Player> &player, charmRune_t runeID, uint8_t action, uint16_t raceid); + void setCharmRuneCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Charm> &charm, uint16_t raceid) const; + void resetCharmRuneCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Charm> &charm) const; int8_t calculateDifficult(uint32_t chance) const; - uint8_t getKillStatus(const std::shared_ptr<MonsterType> mtype, uint32_t killAmount) const; + uint8_t getKillStatus(const std::shared_ptr<MonsterType> &mtype, uint32_t killAmount) const; - uint16_t getBestiaryRaceUnlocked(std::shared_ptr<Player> player, BestiaryType_t race) const; + uint16_t getBestiaryRaceUnlocked(const std::shared_ptr<Player> &player, BestiaryType_t race) const; - int32_t bitToggle(int32_t input, const std::shared_ptr<Charm> charm, bool on) const; + int32_t bitToggle(int32_t input, const std::shared_ptr<Charm> &charm, bool on) const; - bool hasCharmUnlockedRuneBit(const std::shared_ptr<Charm> charm, int32_t input) const; + bool hasCharmUnlockedRuneBit(const std::shared_ptr<Charm> &charm, int32_t input) const; - std::list<charmRune_t> getCharmUsedRuneBitAll(std::shared_ptr<Player> player); + std::list<charmRune_t> getCharmUsedRuneBitAll(const std::shared_ptr<Player> &player); std::vector<uint16_t> getBestiaryFinished(const std::shared_ptr<Player> &player) const; - charmRune_t getCharmFromTarget(std::shared_ptr<Player> player, const std::shared_ptr<MonsterType> mtype); + charmRune_t getCharmFromTarget(const std::shared_ptr<Player> &player, const std::shared_ptr<MonsterType> &mtype); - std::map<uint16_t, uint32_t> getBestiaryKillCountByMonsterIDs(std::shared_ptr<Player> player, std::map<uint16_t, std::string> mtype_list) const; - std::map<uint8_t, int16_t> getMonsterElements(const std::shared_ptr<MonsterType> mtype) const; + std::map<uint16_t, uint32_t> getBestiaryKillCountByMonsterIDs(const std::shared_ptr<Player> &player, const std::map<uint16_t, std::string> &mtype_list) const; + std::map<uint8_t, int16_t> getMonsterElements(const std::shared_ptr<MonsterType> &mtype) const; std::map<uint16_t, std::string> findRaceByName(const std::string &race, bool Onlystring = true, BestiaryType_t raceNumber = BESTY_RACE_NONE) const; private: diff --git a/src/io/ioguild.cpp b/src/io/ioguild.cpp index 9d3d628a42d..55c29b4155a 100644 --- a/src/io/ioguild.cpp +++ b/src/io/ioguild.cpp @@ -7,9 +7,10 @@ * Website: https://docs.opentibiabr.com/ */ +#include "io/ioguild.hpp" + #include "database/database.hpp" #include "creatures/players/grouping/guild.hpp" -#include "io/ioguild.hpp" std::shared_ptr<Guild> IOGuild::loadGuild(uint32_t guildId) { Database &db = Database::getInstance(); @@ -31,7 +32,7 @@ std::shared_ptr<Guild> IOGuild::loadGuild(uint32_t guildId) { return nullptr; } -void IOGuild::saveGuild(const std::shared_ptr<Guild> guild) { +void IOGuild::saveGuild(const std::shared_ptr<Guild> &guild) { if (!guild) { return; } @@ -66,7 +67,7 @@ void IOGuild::getWarList(uint32_t guildId, GuildWarVector &guildWarVector) { } do { - uint32_t guild1 = result->getNumber<uint32_t>("guild1"); + auto guild1 = result->getNumber<uint32_t>("guild1"); if (guildId != guild1) { guildWarVector.push_back(guild1); } else { diff --git a/src/io/ioguild.hpp b/src/io/ioguild.hpp index cc450841bd1..52a8e7c1cba 100644 --- a/src/io/ioguild.hpp +++ b/src/io/ioguild.hpp @@ -15,7 +15,7 @@ using GuildWarVector = std::vector<uint32_t>; class IOGuild { public: static std::shared_ptr<Guild> loadGuild(uint32_t guildId); - static void saveGuild(const std::shared_ptr<Guild> guild); + static void saveGuild(const std::shared_ptr<Guild> &guild); static uint32_t getGuildIdByName(const std::string &name); static void getWarList(uint32_t guildId, GuildWarVector &guildWarVector); }; diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 17816f969de..c0a6a13f363 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -8,11 +8,16 @@ */ #include "io/iologindata.hpp" + +#include "account/account.hpp" +#include "config/configmanager.hpp" +#include "database/database.hpp" #include "io/functions/iologindata_load_player.hpp" #include "io/functions/iologindata_save_player.hpp" #include "game/game.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/players/wheel/player_wheel.hpp" +#include "creatures/players/player.hpp" #include "lib/metrics/metrics.hpp" #include "enums/account_type.hpp" #include "enums/account_errors.hpp" @@ -21,7 +26,7 @@ bool IOLoginData::gameWorldAuthentication(const std::string &accountDescriptor, Account account(accountDescriptor); account.setProtocolCompat(oldProtocol); - if (AccountErrors_t::Ok != enumFromValue<AccountErrors_t>(account.load())) { + if (AccountErrors_t::Ok != account.load()) { g_logger().error("Couldn't load account [{}].", account.getDescriptor()); return false; } @@ -41,13 +46,13 @@ bool IOLoginData::gameWorldAuthentication(const std::string &accountDescriptor, return false; } - if (AccountErrors_t::Ok != enumFromValue<AccountErrors_t>(account.load())) { + if (AccountErrors_t::Ok != account.load()) { g_logger().error("Failed to load account [{}]", accountDescriptor); return false; } auto [players, result] = account.getAccountPlayers(); - if (AccountErrors_t::Ok != enumFromValue<AccountErrors_t>(result)) { + if (AccountErrors_t::Ok != result) { g_logger().error("Failed to load account [{}] players", accountDescriptor); return false; } @@ -73,41 +78,22 @@ uint8_t IOLoginData::getAccountType(uint32_t accountId) { return result->getNumber<uint8_t>("type"); } -void IOLoginData::updateOnlineStatus(uint32_t guid, bool login) { - static phmap::flat_hash_map<uint32_t, bool> updateOnline; - if ((login && updateOnline.find(guid) != updateOnline.end()) || guid <= 0) { - return; - } - - std::ostringstream query; - if (login) { - g_metrics().addUpDownCounter("players_online", 1); - query << "INSERT INTO `players_online` VALUES (" << guid << ')'; - updateOnline[guid] = true; - } else { - g_metrics().addUpDownCounter("players_online", -1); - query << "DELETE FROM `players_online` WHERE `player_id` = " << guid; - updateOnline.erase(guid); - } - Database::getInstance().executeQuery(query.str()); -} - // The boolean "disableIrrelevantInfo" will deactivate the loading of information that is not relevant to the preload, for example, forge, bosstiary, etc. None of this we need to access if the player is offline -bool IOLoginData::loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool disableIrrelevantInfo /* = true*/) { +bool IOLoginData::loadPlayerById(const std::shared_ptr<Player> &player, uint32_t id, bool disableIrrelevantInfo /* = true*/) { Database &db = Database::getInstance(); std::ostringstream query; query << "SELECT * FROM `players` WHERE `id` = " << id; return loadPlayer(player, db.storeQuery(query.str()), disableIrrelevantInfo); } -bool IOLoginData::loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool disableIrrelevantInfo /* = true*/) { +bool IOLoginData::loadPlayerByName(const std::shared_ptr<Player> &player, const std::string &name, bool disableIrrelevantInfo /* = true*/) { Database &db = Database::getInstance(); std::ostringstream query; query << "SELECT * FROM `players` WHERE `name` = " << db.escapeString(name); return loadPlayer(player, db.storeQuery(query.str()), disableIrrelevantInfo); } -bool IOLoginData::loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool disableIrrelevantInfo /* = false*/) { +bool IOLoginData::loadPlayer(const std::shared_ptr<Player> &player, const DBResult_ptr &result, bool disableIrrelevantInfo /* = false*/) { if (!result || !player) { std::string nullptrType = !result ? "Result" : "Player"; g_logger().warn("[{}] - {} is nullptr", __FUNCTION__, nullptrType); @@ -201,7 +187,7 @@ bool IOLoginData::loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result } } -bool IOLoginData::savePlayer(std::shared_ptr<Player> player) { +bool IOLoginData::savePlayer(const std::shared_ptr<Player> &player) { try { bool success = DBTransaction::executeWithinTransaction([player]() { return savePlayerGuard(player); @@ -219,7 +205,7 @@ bool IOLoginData::savePlayer(std::shared_ptr<Player> player) { return false; } -bool IOLoginData::savePlayerGuard(std::shared_ptr<Player> player) { +bool IOLoginData::savePlayerGuard(const std::shared_ptr<Player> &player) { if (!player) { throw DatabaseException("Player nullptr in function: " + std::string(__FUNCTION__)); } @@ -292,7 +278,7 @@ std::string IOLoginData::getNameByGuid(uint32_t guid) { query << "SELECT `name` FROM `players` WHERE `id` = " << guid; DBResult_ptr result = Database::getInstance().storeQuery(query.str()); if (!result) { - return std::string(); + return {}; } return result->getString("name"); } diff --git a/src/io/iologindata.hpp b/src/io/iologindata.hpp index 79fa3b59ad7..d379031cd55 100644 --- a/src/io/iologindata.hpp +++ b/src/io/iologindata.hpp @@ -9,9 +9,12 @@ #pragma once -#include "account/account.hpp" -#include "creatures/players/player.hpp" -#include "database/database.hpp" +class Player; +class Item; +class DBResult; + +struct VIPEntry; +struct VIPGroupEntry; using ItemBlockList = std::list<std::pair<int32_t, std::shared_ptr<Item>>>; @@ -19,11 +22,10 @@ class IOLoginData { public: static bool gameWorldAuthentication(const std::string &accountDescriptor, const std::string &sessionOrPassword, std::string &characterName, uint32_t &accountId, bool oldProcotol, const uint32_t ip); static uint8_t getAccountType(uint32_t accountId); - static void updateOnlineStatus(uint32_t guid, bool login); - static bool loadPlayerById(std::shared_ptr<Player> player, uint32_t id, bool disableIrrelevantInfo = true); - static bool loadPlayerByName(std::shared_ptr<Player> player, const std::string &name, bool disableIrrelevantInfo = true); - static bool loadPlayer(std::shared_ptr<Player> player, DBResult_ptr result, bool disableIrrelevantInfo = false); - static bool savePlayer(std::shared_ptr<Player> player); + static bool loadPlayerById(const std::shared_ptr<Player> &player, uint32_t id, bool disableIrrelevantInfo = true); + static bool loadPlayerByName(const std::shared_ptr<Player> &player, const std::string &name, bool disableIrrelevantInfo = true); + static bool loadPlayer(const std::shared_ptr<Player> &player, const std::shared_ptr<DBResult> &result, bool disableIrrelevantInfo = false); + static bool savePlayer(const std::shared_ptr<Player> &player); static uint32_t getGuidByName(const std::string &name); static bool getGuidByNameEx(uint32_t &guid, bool &specialVip, std::string &name); static std::string getNameByGuid(uint32_t guid); @@ -44,5 +46,5 @@ class IOLoginData { static void removeGuidVIPGroupEntry(uint32_t accountId, uint32_t guid); private: - static bool savePlayerGuard(std::shared_ptr<Player> player); + static bool savePlayerGuard(const std::shared_ptr<Player> &player); }; diff --git a/src/io/iomap.cpp b/src/io/iomap.cpp index d39988caa71..922613c0350 100644 --- a/src/io/iomap.cpp +++ b/src/io/iomap.cpp @@ -8,6 +8,7 @@ */ #include "io/iomap.hpp" + #include "game/movement/teleport.hpp" #include "game/game.hpp" #include "io/filestream.hpp" @@ -134,7 +135,7 @@ void IOMap::parseTileArea(FileStream &stream, Map &map, const Position &pos) { const uint16_t x = base_x + tileCoordsX + pos.x; const uint16_t y = base_y + tileCoordsY + pos.y; - const uint8_t z = static_cast<uint8_t>(base_z + pos.z); + const auto z = static_cast<uint8_t>(base_z + pos.z); if (tileType == OTBM_HOUSETILE) { tile->houseId = stream.getU32(); diff --git a/src/io/iomap.hpp b/src/io/iomap.hpp index b730f664853..6ac74690460 100644 --- a/src/io/iomap.hpp +++ b/src/io/iomap.hpp @@ -11,6 +11,7 @@ #include "declarations.hpp" +// TODO: move to .cpp for avoid circular dependencies #include "config/configmanager.hpp" #include "map/house/house.hpp" #include "items/item.hpp" @@ -157,8 +158,8 @@ class IOMap { class IOMapException : public std::exception { public: - explicit IOMapException(const std::string &msg) : - message(msg) { } + explicit IOMapException(std::string msg) : + message(std::move(msg)) { } const char* what() const noexcept override { return message.c_str(); diff --git a/src/io/iomapserialize.cpp b/src/io/iomapserialize.cpp index 4c20d8a6aa1..b1de604dd14 100644 --- a/src/io/iomapserialize.cpp +++ b/src/io/iomapserialize.cpp @@ -8,6 +8,8 @@ */ #include "io/iomapserialize.hpp" + +#include "config/configmanager.hpp" #include "io/iologindata.hpp" #include "game/game.hpp" #include "items/bed.hpp" @@ -108,7 +110,7 @@ bool IOMapSerialize::SaveHouseItemsGuard() { return true; } -bool IOMapSerialize::loadContainer(PropStream &propStream, std::shared_ptr<Container> container) { +bool IOMapSerialize::loadContainer(PropStream &propStream, const std::shared_ptr<Container> &container) { while (container->serializationCount > 0) { if (!loadItem(propStream, container)) { g_logger().warn("Deserialization error for container item: {}", container->getID()); @@ -125,7 +127,7 @@ bool IOMapSerialize::loadContainer(PropStream &propStream, std::shared_ptr<Conta return true; } -bool IOMapSerialize::loadItem(PropStream &propStream, std::shared_ptr<Cylinder> parent, bool isHouseItem /*= false*/) { +bool IOMapSerialize::loadItem(PropStream &propStream, const std::shared_ptr<Cylinder> &parent, bool isHouseItem /*= false*/) { uint16_t id; if (!propStream.read<uint16_t>(id)) { return false; @@ -214,8 +216,8 @@ bool IOMapSerialize::loadItem(PropStream &propStream, std::shared_ptr<Cylinder> return true; } -void IOMapSerialize::saveItem(PropWriteStream &stream, std::shared_ptr<Item> item) { - std::shared_ptr<Container> container = item->getContainer(); +void IOMapSerialize::saveItem(PropWriteStream &stream, const std::shared_ptr<Item> &item) { + const auto &container = item->getContainer(); // Write ID & props stream.write<uint16_t>(item->getID()); @@ -233,7 +235,7 @@ void IOMapSerialize::saveItem(PropWriteStream &stream, std::shared_ptr<Item> ite stream.write<uint8_t>(0x00); // attr end } -void IOMapSerialize::saveTile(PropWriteStream &stream, std::shared_ptr<Tile> tile) { +void IOMapSerialize::saveTile(PropWriteStream &stream, const std::shared_ptr<Tile> &tile) { const TileItemVector* tileItems = tile->getItemList(); if (!tileItems) { return; @@ -280,8 +282,8 @@ bool IOMapSerialize::loadHouseInfo() { auto houseId = result->getNumber<uint32_t>("id"); const auto house = g_game().map.houses.getHouse(houseId); if (house) { - uint32_t owner = result->getNumber<uint32_t>("owner"); - int32_t newOwner = result->getNumber<int32_t>("new_owner"); + auto owner = result->getNumber<uint32_t>("owner"); + auto newOwner = result->getNumber<int32_t>("new_owner"); // Transfer house owner auto isTransferOnRestart = g_configManager().getBoolean(TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART); if (isTransferOnRestart && newOwner >= 0) { @@ -368,7 +370,7 @@ bool IOMapSerialize::SaveHouseInfoGuard() { listText.clear(); } - for (std::shared_ptr<Door> door : house->getDoors()) { + for (const std::shared_ptr<Door> &door : house->getDoors()) { if (door->getAccessList(listText) && !listText.empty()) { query << house->getId() << ',' << door->getDoorId() << ',' << db.escapeString(listText) << ',' << version; if (!listUpdate.addRow(query)) { diff --git a/src/io/iomapserialize.hpp b/src/io/iomapserialize.hpp index 08cbac01128..ae1c9ccb5f1 100644 --- a/src/io/iomapserialize.hpp +++ b/src/io/iomapserialize.hpp @@ -21,9 +21,9 @@ class IOMapSerialize { private: static bool SaveHouseInfoGuard(); static bool SaveHouseItemsGuard(); - static void saveItem(PropWriteStream &stream, std::shared_ptr<Item> item); - static void saveTile(PropWriteStream &stream, std::shared_ptr<Tile> tile); + static void saveItem(PropWriteStream &stream, const std::shared_ptr<Item> &item); + static void saveTile(PropWriteStream &stream, const std::shared_ptr<Tile> &tile); - static bool loadContainer(PropStream &propStream, std::shared_ptr<Container> container); - static bool loadItem(PropStream &propStream, std::shared_ptr<Cylinder> parent, bool isHouseItem = false); + static bool loadContainer(PropStream &propStream, const std::shared_ptr<Container> &container); + static bool loadItem(PropStream &propStream, const std::shared_ptr<Cylinder> &parent, bool isHouseItem = false); }; diff --git a/src/io/iomarket.cpp b/src/io/iomarket.cpp index 72f245c56d6..fe91b3f6d94 100644 --- a/src/io/iomarket.cpp +++ b/src/io/iomarket.cpp @@ -8,11 +8,15 @@ */ #include "io/iomarket.hpp" + +#include "config/configmanager.hpp" #include "database/databasetasks.hpp" -#include "io/iologindata.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/save_manager.hpp" +#include "io/iologindata.hpp" +#include "items/containers/inbox/inbox.hpp" +#include "creatures/players/player.hpp" uint8_t IOMarket::getTierFromDatabaseTable(const std::string &string) { auto tier = static_cast<uint8_t>(std::atoi(string.c_str())); @@ -128,7 +132,7 @@ HistoryMarketOfferList IOMarket::getOwnHistory(MarketAction_t action, uint32_t p } do { - HistoryMarketOffer offer; + HistoryMarketOffer offer {}; offer.itemId = result->getNumber<uint16_t>("itemtype"); offer.amount = result->getNumber<uint16_t>("amount"); offer.price = result->getNumber<uint64_t>("price"); @@ -147,7 +151,7 @@ HistoryMarketOfferList IOMarket::getOwnHistory(MarketAction_t action, uint32_t p return offerList; } -void IOMarket::processExpiredOffers(DBResult_ptr result, bool) { +void IOMarket::processExpiredOffers(const DBResult_ptr &result, bool) { if (!result) { return; } @@ -157,8 +161,8 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool) { continue; } - const uint32_t playerId = result->getNumber<uint32_t>("player_id"); - const uint16_t amount = result->getNumber<uint16_t>("amount"); + const auto playerId = result->getNumber<uint32_t>("player_id"); + const auto amount = result->getNumber<uint16_t>("amount"); auto tier = getTierFromDatabaseTable(result->getString("tier")); if (result->getNumber<uint16_t>("sale") == 1) { const ItemType &itemType = Item::items[result->getNumber<uint16_t>("itemtype")]; @@ -166,17 +170,19 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool) { continue; } - std::shared_ptr<Player> player = g_game().getPlayerByGUID(playerId, true); + const auto &player = g_game().getPlayerByGUID(playerId, true); if (!player) { continue; } + const auto &playerInbox = player->getInbox(); + if (itemType.stackable) { uint16_t tmpAmount = amount; while (tmpAmount > 0) { uint16_t stackCount = std::min<uint16_t>(100, tmpAmount); - std::shared_ptr<Item> item = Item::CreateItem(itemType.id, stackCount); - if (g_game().internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(itemType.id, stackCount); + if (g_game().internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { g_logger().error("[{}] Ocurred an error to add item with id {} to player {}", __FUNCTION__, itemType.id, player->getName()); break; @@ -197,8 +203,8 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool) { } for (uint16_t i = 0; i < amount; ++i) { - std::shared_ptr<Item> item = Item::CreateItem(itemType.id, subType); - if (g_game().internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { + const auto &item = Item::CreateItem(itemType.id, subType); + if (g_game().internalAddItem(playerInbox, item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { break; } @@ -214,7 +220,7 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool) { } else { uint64_t totalPrice = result->getNumber<uint64_t>("price") * amount; - std::shared_ptr<Player> player = g_game().getPlayerByGUID(playerId); + const auto &player = g_game().getPlayerByGUID(playerId); if (player) { player->setBankBalance(player->getBankBalance() + totalPrice); } else { diff --git a/src/io/iomarket.hpp b/src/io/iomarket.hpp index 4292651fb47..5a078bbc1cb 100644 --- a/src/io/iomarket.hpp +++ b/src/io/iomarket.hpp @@ -26,7 +26,7 @@ class IOMarket { static MarketOfferList getOwnOffers(MarketAction_t action, uint32_t playerId); static HistoryMarketOfferList getOwnHistory(MarketAction_t action, uint32_t playerId); - static void processExpiredOffers(DBResult_ptr result, bool); + static void processExpiredOffers(const DBResult_ptr &result, bool); static void checkExpiredOffers(); static uint32_t getPlayerOfferCount(uint32_t playerId); diff --git a/src/io/ioprey.cpp b/src/io/ioprey.cpp index b21f442bf67..65838a1660c 100644 --- a/src/io/ioprey.cpp +++ b/src/io/ioprey.cpp @@ -9,14 +9,13 @@ #include "io/ioprey.hpp" -#include "lib/di/container.hpp" -#include "creatures/monsters/monster.hpp" -#include "creatures/players/player.hpp" #include "config/configmanager.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" +#include "lib/di/container.hpp" #include "lib/metrics/metrics.hpp" #include "server/network/message/networkmessage.hpp" -#include "server/network/protocol/protocolgame.hpp" // Prey class PreySlot::PreySlot(PreySlot_t id) : @@ -253,7 +252,7 @@ IOPrey &IOPrey::getInstance() { } // Prey/Task hunting global class -void IOPrey::checkPlayerPreys(std::shared_ptr<Player> player, uint8_t amount) const { +void IOPrey::checkPlayerPreys(const std::shared_ptr<Player> &player, uint8_t amount) const { if (!player) { return; } @@ -297,7 +296,7 @@ void IOPrey::checkPlayerPreys(std::shared_ptr<Player> player, uint8_t amount) co } } -void IOPrey::parsePreyAction(std::shared_ptr<Player> player, PreySlot_t slotId, PreyAction_t action, PreyOption_t option, int8_t index, uint16_t raceId) const { +void IOPrey::parsePreyAction(const std::shared_ptr<Player> &player, PreySlot_t slotId, PreyAction_t action, PreyOption_t option, int8_t index, uint16_t raceId) const { const auto &slot = player->getPreySlotById(slotId); if (!slot || slot->state == PreyDataState_Locked) { player->sendMessageDialog("To unlock this prey slot first you must buy it on store."); @@ -403,7 +402,7 @@ void IOPrey::parsePreyAction(std::shared_ptr<Player> player, PreySlot_t slotId, player->reloadPreySlot(slotId); } -void IOPrey::parseTaskHuntingAction(std::shared_ptr<Player> player, PreySlot_t slotId, PreyTaskAction_t action, bool upgrade, uint16_t raceId) const { +void IOPrey::parseTaskHuntingAction(const std::shared_ptr<Player> &player, PreySlot_t slotId, PreyTaskAction_t action, bool upgrade, uint16_t raceId) const { const auto &slot = player->getTaskHuntingSlotById(slotId); if (!slot || slot->state == PreyTaskDataState_Locked) { player->sendMessageDialog("To unlock this task hunting slot first you must buy it on store."); diff --git a/src/io/ioprey.hpp b/src/io/ioprey.hpp index df7243df6d6..b7470563d60 100644 --- a/src/io/ioprey.hpp +++ b/src/io/ioprey.hpp @@ -225,10 +225,10 @@ class IOPrey { static IOPrey &getInstance(); - void checkPlayerPreys(std::shared_ptr<Player> player, uint8_t amount) const; - void parsePreyAction(std::shared_ptr<Player> player, PreySlot_t slotId, PreyAction_t action, PreyOption_t option, int8_t index, uint16_t raceId) const; + void checkPlayerPreys(const std::shared_ptr<Player> &player, uint8_t amount) const; + void parsePreyAction(const std::shared_ptr<Player> &player, PreySlot_t slotId, PreyAction_t action, PreyOption_t option, int8_t index, uint16_t raceId) const; - void parseTaskHuntingAction(std::shared_ptr<Player> player, PreySlot_t slotId, PreyTaskAction_t action, bool upgrade, uint16_t raceId) const; + void parseTaskHuntingAction(const std::shared_ptr<Player> &player, PreySlot_t slotId, PreyTaskAction_t action, bool upgrade, uint16_t raceId) const; void initializeTaskHuntOptions(); const std::unique_ptr<TaskHuntingOption> &getTaskRewardOption(const std::unique_ptr<TaskHuntingSlot> &slot) const; diff --git a/src/items/bed.cpp b/src/items/bed.cpp index e40a0f85e0f..527f052e2d0 100644 --- a/src/items/bed.cpp +++ b/src/items/bed.cpp @@ -8,10 +8,15 @@ */ #include "items/bed.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" #include "game/game.hpp" -#include "io/iologindata.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/save_manager.hpp" +#include "io/iologindata.hpp" +#include "server/network/protocol/protocolgame.hpp" +#include "creatures/players/player.hpp" BedItem::BedItem(uint16_t id) : Item(id) { @@ -27,7 +32,7 @@ Attr_ReadValue BedItem::readAttr(AttrTypes_t attr, PropStream &propStream) { } if (guid != 0) { - std::string name = IOLoginData::getNameByGuid(guid); + const std::string name = IOLoginData::getNameByGuid(guid); if (!name.empty()) { setAttribute(ItemAttribute_t::DESCRIPTION, name + " is sleeping there."); g_game().setBedSleeper(static_self_cast<BedItem>(), guid); @@ -67,22 +72,22 @@ void BedItem::serializeAttr(PropWriteStream &propWriteStream) const { } std::shared_ptr<BedItem> BedItem::getNextBedItem() { - Direction dir = Item::items[id].bedPartnerDir; - Position targetPos = getNextPosition(dir, getPosition()); + const Direction dir = Item::items[id].bedPartnerDir; + const Position targetPos = getNextPosition(dir, getPosition()); - std::shared_ptr<Tile> tile = g_game().map.getTile(targetPos); + const auto &tile = g_game().map.getTile(targetPos); if (tile == nullptr) { return nullptr; } return tile->getBedItem(); } -bool BedItem::canUse(std::shared_ptr<Player> player) { +bool BedItem::canUse(const std::shared_ptr<Player> &player) { if ((player == nullptr) || (house == nullptr) || !player->isPremium()) { return false; } - auto nextBedItem = getNextBedItem(); + const auto &nextBedItem = getNextBedItem(); if (nextBedItem == nullptr) { return false; } @@ -104,7 +109,7 @@ bool BedItem::canUse(std::shared_ptr<Player> player) { return true; } - auto sleeper = std::make_shared<Player>(nullptr); + const auto sleeper = std::make_shared<Player>(nullptr); if (!IOLoginData::loadPlayerById(sleeper, sleeperGUID)) { return false; } @@ -115,7 +120,7 @@ bool BedItem::canUse(std::shared_ptr<Player> player) { return true; } -bool BedItem::isBedComplete(std::shared_ptr<BedItem> nextBedItem) { +bool BedItem::isBedComplete(const std::shared_ptr<BedItem> &nextBedItem) const { const ItemType &it = Item::items[id]; if (nextBedItem == nullptr) { @@ -132,7 +137,7 @@ bool BedItem::isBedComplete(std::shared_ptr<BedItem> nextBedItem) { return it.bedPartOf == nextBedItem->getID(); } -bool BedItem::trySleep(std::shared_ptr<Player> player) { +bool BedItem::trySleep(const std::shared_ptr<Player> &player) { if (!house || player->isRemoved()) { return false; } @@ -148,7 +153,7 @@ bool BedItem::trySleep(std::shared_ptr<Player> player) { return true; } -bool BedItem::sleep(std::shared_ptr<Player> player) { +bool BedItem::sleep(const std::shared_ptr<Player> &player) { if (house == nullptr) { return false; } @@ -157,7 +162,7 @@ bool BedItem::sleep(std::shared_ptr<Player> player) { return false; } - std::shared_ptr<BedItem> nextBedItem = getNextBedItem(); + const auto &nextBedItem = getNextBedItem(); internalSetSleeper(player); @@ -191,7 +196,7 @@ bool BedItem::sleep(std::shared_ptr<Player> player) { return true; } -void BedItem::wakeUp(std::shared_ptr<Player> player) { +void BedItem::wakeUp(const std::shared_ptr<Player> &player) { if (house == nullptr) { return; } @@ -215,7 +220,7 @@ void BedItem::wakeUp(std::shared_ptr<Player> player) { // update the bedSleepersMap g_game().removeBedSleeper(sleeperGUID); - std::shared_ptr<BedItem> nextBedItem = getNextBedItem(); + const auto &nextBedItem = getNextBedItem(); // unset sleep info internalRemoveSleeper(); @@ -232,10 +237,10 @@ void BedItem::wakeUp(std::shared_ptr<Player> player) { } } -void BedItem::regeneratePlayer(std::shared_ptr<Player> player) const { +void BedItem::regeneratePlayer(const std::shared_ptr<Player> &player) const { const uint32_t sleptTime = time(nullptr) - sleepStart; - std::shared_ptr<Condition> condition = player->getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); + const auto &condition = player->getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); if (condition != nullptr) { uint32_t regen; if (condition->getTicks() != -1) { @@ -258,7 +263,7 @@ void BedItem::regeneratePlayer(std::shared_ptr<Player> player) const { player->changeSoul(soulRegen); } -void BedItem::updateAppearance(std::shared_ptr<Player> player) { +void BedItem::updateAppearance(const std::shared_ptr<Player> &player) { const ItemType &it = Item::items[id]; if (it.type == ITEM_TYPE_BED) { if ((player != nullptr) && it.transformToOnUse[player->getSex()] != 0) { @@ -275,8 +280,8 @@ void BedItem::updateAppearance(std::shared_ptr<Player> player) { } } -void BedItem::internalSetSleeper(std::shared_ptr<Player> player) { - std::string desc_str = player->getName() + " is sleeping there."; +void BedItem::internalSetSleeper(const std::shared_ptr<Player> &player) { + const std::string desc_str = player->getName() + " is sleeping there."; sleeperGUID = player->getGUID(); sleepStart = time(nullptr); diff --git a/src/items/bed.hpp b/src/items/bed.hpp index 2aeb6e38e5b..725db01ea1b 100644 --- a/src/items/bed.hpp +++ b/src/items/bed.hpp @@ -37,25 +37,25 @@ class BedItem final : public Item { house = h; } - bool canUse(std::shared_ptr<Player> player); + bool canUse(const std::shared_ptr<Player> &player); - bool isBedComplete(std::shared_ptr<BedItem> nextBedItem); + bool isBedComplete(const std::shared_ptr<BedItem> &nextBedItem) const; - bool trySleep(std::shared_ptr<Player> player); - bool sleep(std::shared_ptr<Player> player); - void wakeUp(std::shared_ptr<Player> player); + bool trySleep(const std::shared_ptr<Player> &player); + bool sleep(const std::shared_ptr<Player> &player); + void wakeUp(const std::shared_ptr<Player> &player); std::shared_ptr<BedItem> getNextBedItem(); friend class MapCache; private: - void updateAppearance(std::shared_ptr<Player> player); - void regeneratePlayer(std::shared_ptr<Player> player) const; - void internalSetSleeper(std::shared_ptr<Player> player); + void updateAppearance(const std::shared_ptr<Player> &player); + void regeneratePlayer(const std::shared_ptr<Player> &player) const; + void internalSetSleeper(const std::shared_ptr<Player> &player); void internalRemoveSleeper(); std::shared_ptr<House> house; - uint64_t sleepStart; - uint32_t sleeperGUID; + uint64_t sleepStart {}; + uint32_t sleeperGUID {}; }; diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index 595ae38dedf..77a37942e37 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -8,8 +8,9 @@ */ #include "items/containers/container.hpp" -#include "items/decay/decay.hpp" -#include "io/iomap.hpp" + +#include "config/configmanager.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" #include "map/spectators.hpp" @@ -43,27 +44,43 @@ std::shared_ptr<Container> Container::create(uint16_t type, uint16_t size, bool return std::make_shared<Container>(type, size, unlocked, pagination); } -std::shared_ptr<Container> Container::create(std::shared_ptr<Tile> tile) { - auto container = std::make_shared<Container>(ITEM_BROWSEFIELD, 30, false, true); - TileItemVector* itemVector = tile->getItemList(); +std::shared_ptr<Container> Container::createBrowseField(const std::shared_ptr<Tile> &tile) { + const auto &newContainer = create(ITEM_BROWSEFIELD, 30, false, true); + if (!newContainer || !tile) { + return nullptr; + } + + const TileItemVector* itemVector = tile->getItemList(); if (itemVector) { - for (auto &item : *itemVector) { - if (((item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE)) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH))) && !item->hasAttribute(ItemAttribute_t::UNIQUEID)) { - container->itemlist.push_front(item); - item->setParent(container); + for (const auto &item : *itemVector) { + if (!item) { + continue; } + + // Checks if the item has an internal container, is movable, or is packable without blocking the path. + bool isItemValid = item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH)); + + // If the item has a unique ID or is not valid, skip to the next item. + if (item->hasAttribute(ItemAttribute_t::UNIQUEID) || !isItemValid) { + continue; + } + + // Add the item to the new container and set its parent. + newContainer->itemlist.push_front(item); + item->setParent(newContainer); } } - container->setParent(tile); - return container; + // Set the parent of the new container to be the tile. + newContainer->setParent(tile); + return newContainer; } Container::~Container() { if (getID() == ITEM_BROWSEFIELD) { - auto parent = getParent(); + const auto &parent = getParent(); if (parent) { - auto tile = parent->getTile(); + const auto &tile = parent->getTile(); if (tile) { auto browseField = g_game().browseFields.find(tile); if (browseField != g_game().browseFields.end()) { @@ -81,8 +98,8 @@ Container::~Container() { } std::shared_ptr<Item> Container::clone() const { - std::shared_ptr<Container> clone = std::static_pointer_cast<Container>(Item::clone()); - for (std::shared_ptr<Item> item : itemlist) { + const std::shared_ptr<Container> &clone = std::static_pointer_cast<Container>(Item::clone()); + for (const std::shared_ptr<Item> &item : itemlist) { clone->addItem(item->clone()); } clone->totalWeight = totalWeight; @@ -90,7 +107,7 @@ std::shared_ptr<Item> Container::clone() const { } std::shared_ptr<Container> Container::getParentContainer() { - std::shared_ptr<Thing> thing = getParent(); + const std::shared_ptr<Thing> &thing = getParent(); if (!thing) { return nullptr; } @@ -121,31 +138,31 @@ std::shared_ptr<Container> Container::getRootContainer() { } bool Container::hasParent() { - auto parent = getParent(); + const auto &parent = getParent(); if (!parent) { return false; } - auto creature = parent->getCreature(); - bool isPlayer = creature && creature->getPlayer() != nullptr; + const auto &creature = parent->getCreature(); + const bool &isPlayer = creature && creature->getPlayer() != nullptr; return getID() != ITEM_BROWSEFIELD && !isPlayer; } -void Container::addItem(std::shared_ptr<Item> item) { +void Container::addItem(const std::shared_ptr<Item> &item) { itemlist.push_back(item); item->setParent(getContainer()); } StashContainerList Container::getStowableItems() const { StashContainerList toReturnList; - for (auto item : itemlist) { - if (item->getContainer() != NULL) { - auto subContainer = item->getContainer()->getStowableItems(); - for (auto subContItem : subContainer) { - std::shared_ptr<Item> containerItem = subContItem.first; - toReturnList.push_back(std::pair<std::shared_ptr<Item>, uint32_t>(containerItem, static_cast<uint32_t>(containerItem->getItemCount()))); + for (const auto &item : itemlist) { + if (item->getContainer() != nullptr) { + const auto &subContainer = item->getContainer()->getStowableItems(); + for (const auto &key : subContainer | std::views::keys) { + const auto &containerItem = key; + toReturnList.emplace_back(containerItem, static_cast<uint32_t>(containerItem->getItemCount())); } } else if (item->isItemStorable()) { - toReturnList.push_back(std::pair<std::shared_ptr<Item>, uint32_t>(item, static_cast<uint32_t>(item->getItemCount()))); + toReturnList.emplace_back(item, static_cast<uint32_t>(item->getItemCount())); } } @@ -163,12 +180,12 @@ Attr_ReadValue Container::readAttr(AttrTypes_t attr, PropStream &propStream) { } bool Container::unserializeItemNode(OTB::Loader &loader, const OTB::Node &node, PropStream &propStream, Position &itemPosition) { - bool ret = Item::unserializeItemNode(loader, node, propStream, itemPosition); + const bool ret = Item::unserializeItemNode(loader, node, propStream, itemPosition); if (!ret) { return false; } - for (auto &itemNode : node.children) { + for (const auto &itemNode : node.children) { // load container items if (itemNode.type != OTBM_ITEM) { // unknown type @@ -185,7 +202,7 @@ bool Container::unserializeItemNode(OTB::Loader &loader, const OTB::Node &node, return false; } - std::shared_ptr<Item> item = Item::CreateItem(id, itemPosition); + const auto &item = Item::CreateItem(id, itemPosition); if (!item) { continue; } @@ -200,7 +217,7 @@ bool Container::unserializeItemNode(OTB::Loader &loader, const OTB::Node &node, return true; } -bool Container::countsToLootAnalyzerBalance() { +bool Container::countsToLootAnalyzerBalance() const { if (isCorpse()) { return true; } @@ -232,9 +249,12 @@ std::string Container::getContentDescription(bool oldProtocol) { std::ostringstream &Container::getContentDescription(std::ostringstream &os, bool sendColoredMessage) { bool firstitem = true; for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; + const auto &item = *it; + if (!item) { + continue; + } - std::shared_ptr<Container> container = item->getContainer(); + const auto &container = item->getContainer(); if (container && !container->empty()) { continue; } @@ -267,7 +287,7 @@ bool Container::isStoreInbox() const { } bool Container::isStoreInboxFiltered() const { - auto attribute = getAttribute<std::string>(ItemAttribute_t::STORE_INBOX_CATEGORY); + const auto attribute = getAttribute<std::string>(ItemAttribute_t::STORE_INBOX_CATEGORY); if (isStoreInbox() && !attribute.empty() && attribute != "All") { return true; } @@ -279,10 +299,10 @@ std::deque<std::shared_ptr<Item>> Container::getStoreInboxFilteredItems() const const auto enumName = getAttribute<std::string>(ItemAttribute_t::STORE_INBOX_CATEGORY); ItemDeque storeInboxFilteredList; if (isStoreInboxFiltered()) { - for (std::shared_ptr<Item> item : getItemList()) { + for (const std::shared_ptr<Item> &item : getItemList()) { auto itemId = item->getID(); - auto attribute = item->getCustomAttribute("unWrapId"); - uint16_t unWrapId = attribute ? static_cast<uint16_t>(attribute->getInteger()) : 0; + const auto attribute = item->getCustomAttribute("unWrapId"); + const uint16_t unWrapId = attribute ? static_cast<uint16_t>(attribute->getInteger()) : 0; if (unWrapId != 0) { itemId = unWrapId; } @@ -303,8 +323,8 @@ std::vector<ContainerCategory_t> Container::getStoreInboxValidCategories() const stdext::vector_set<ContainerCategory_t> validCategories; for (const auto &item : itemlist) { auto itemId = item->getID(); - auto attribute = item->getCustomAttribute("unWrapId"); - uint16_t unWrapId = attribute ? static_cast<uint16_t>(attribute->getInteger()) : 0; + const auto attribute = item->getCustomAttribute("unWrapId"); + const uint16_t unWrapId = attribute ? static_cast<uint16_t>(attribute->getInteger()) : 0; if (unWrapId != 0) { itemId = unWrapId; } @@ -322,14 +342,14 @@ std::vector<ContainerCategory_t> Container::getStoreInboxValidCategories() const } std::shared_ptr<Item> Container::getFilteredItemByIndex(size_t index) const { - const auto filteredItems = getStoreInboxFilteredItems(); + const auto &filteredItems = getStoreInboxFilteredItems(); if (index >= filteredItems.size()) { return nullptr; } - auto item = filteredItems[index]; + const auto &item = filteredItems[index]; - auto it = std::find(itemlist.begin(), itemlist.end(), item); + const auto it = std::ranges::find(itemlist, item); if (it == itemlist.end()) { return nullptr; } @@ -363,9 +383,14 @@ uint32_t Container::getContainerHoldingCount() { return counter; } -bool Container::isHoldingItem(std::shared_ptr<Item> item) { +bool Container::isHoldingItem(const std::shared_ptr<Item> &item) { for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - if (*it == item) { + const auto &compareItem = *it; + if (!compareItem || !item) { + continue; + } + + if (compareItem == item) { return true; } } @@ -374,8 +399,12 @@ bool Container::isHoldingItem(std::shared_ptr<Item> item) { bool Container::isHoldingItemWithId(const uint16_t id) { for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - std::shared_ptr<Item> item = *it; - if (item->getID() == id) { + const auto &item = *it; + if (!item) { + continue; + } + + if (item && item->getID() == id) { return true; } } @@ -405,8 +434,8 @@ bool Container::isBrowseFieldAndHoldsRewardChest() { return getID() == ITEM_BROWSEFIELD && isHoldingItemWithId(ITEM_REWARD_CHEST); } -void Container::onAddContainerItem(std::shared_ptr<Item> item) { - auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); +void Container::onAddContainerItem(const std::shared_ptr<Item> &item) { + const auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); // send to client for (const auto &spectator : spectators) { @@ -419,8 +448,8 @@ void Container::onAddContainerItem(std::shared_ptr<Item> item) { } } -void Container::onUpdateContainerItem(uint32_t index, std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem) { - auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); +void Container::onUpdateContainerItem(uint32_t index, const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem) { + const auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); // send to client for (const auto &spectator : spectators) { @@ -433,8 +462,8 @@ void Container::onUpdateContainerItem(uint32_t index, std::shared_ptr<Item> oldI } } -void Container::onRemoveContainerItem(uint32_t index, std::shared_ptr<Item> item) { - auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); +void Container::onRemoveContainerItem(uint32_t index, const std::shared_ptr<Item> &item) { + const auto spectators = Spectators().find<Player>(getPosition(), false, 2, 2, 2, 2); // send change to client for (const auto &spectator : spectators) { @@ -447,8 +476,8 @@ void Container::onRemoveContainerItem(uint32_t index, std::shared_ptr<Item> item } } -ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> &addThing, uint32_t addCount, uint32_t flags, std::shared_ptr<Creature> actor /* = nullptr*/) { - bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); +ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> &addThing, uint32_t addCount, uint32_t flags, const std::shared_ptr<Creature> &actor /* = nullptr*/) { + const bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); if (childIsOwner) { // a child container is querying, since we are the top container (not carried by a player) // just return with no error. @@ -459,7 +488,7 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Item> item = addThing->getItem(); + const auto &item = addThing->getItem(); if (item == nullptr) { return RETURNVALUE_NOTPOSSIBLE; } @@ -473,7 +502,7 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & } if (item->hasOwner()) { // a non-owner can move the item around but not pick it up - auto toPlayer = getTopParent()->getPlayer(); + const auto &toPlayer = getTopParent()->getPlayer(); if (toPlayer && !item->isOwner(toPlayer)) { return RETURNVALUE_ITEMISNOTYOURS; } @@ -485,16 +514,16 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & } std::shared_ptr<Cylinder> cylinder = getParent(); - auto noLimit = hasBitSet(FLAG_NOLIMIT, flags); + const auto noLimit = hasBitSet(FLAG_NOLIMIT, flags); while (cylinder) { if (cylinder == addThing) { return RETURNVALUE_THISISIMPOSSIBLE; } - std::shared_ptr<Container> container = cylinder->getContainer(); + const std::shared_ptr<Container> &container = cylinder->getContainer(); if (!noLimit && container && container->isInbox()) { return RETURNVALUE_CONTAINERNOTENOUGHROOM; } - std::shared_ptr<Cylinder> parent = cylinder->getParent(); + const std::shared_ptr<Cylinder> &parent = cylinder->getParent(); if (cylinder == parent) { g_logger().error("Container::queryAdd: parent == cylinder. Preventing infinite loop."); return RETURNVALUE_NOTPOSSIBLE; @@ -514,7 +543,7 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & return RETURNVALUE_CONTAINERISFULL; } - uint32_t addItemCount = addContainer->getItemHoldingCount() + 1; + const uint32_t addItemCount = addContainer->getItemHoldingCount() + 1; if (addItemCount + topParentContainer->getItemHoldingCount() > m_maxItems) { return RETURNVALUE_CONTAINERISFULL; } @@ -529,7 +558,7 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & return RETURNVALUE_ONLYAMMOINQUIVER; } - std::shared_ptr<Cylinder> topParent = getTopParent(); + const std::shared_ptr<Cylinder> &topParent = getTopParent(); if (topParent != getContainer()) { return topParent->queryAdd(INDEX_WHEREEVER, item, addCount, flags | FLAG_CHILDISOWNER, actor); } else { @@ -538,7 +567,7 @@ ReturnValue Container::queryAdd(int32_t addIndex, const std::shared_ptr<Thing> & } ReturnValue Container::queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { maxQueryCount = 0; return RETURNVALUE_NOTPOSSIBLE; @@ -549,7 +578,7 @@ ReturnValue Container::queryMaxCount(int32_t index, const std::shared_ptr<Thing> return RETURNVALUE_NOERROR; } - int32_t freeSlots = std::max<int32_t>(capacity() - size(), 0); + const int32_t freeSlots = std::max<int32_t>(capacity() - size(), 0); if (item->isStackable()) { uint32_t n = 0; @@ -557,16 +586,16 @@ ReturnValue Container::queryMaxCount(int32_t index, const std::shared_ptr<Thing> if (index == INDEX_WHEREEVER) { // Iterate through every item and check how much free stackable slots there is. uint32_t slotIndex = 0; - for (std::shared_ptr<Item> containerItem : itemlist) { + for (const auto &containerItem : itemlist) { if (containerItem != item && containerItem->equals(item) && containerItem->getItemCount() < containerItem->getStackSize()) { - uint32_t remainder = (containerItem->getStackSize() - containerItem->getItemCount()); + const uint32_t remainder = (containerItem->getStackSize() - containerItem->getItemCount()); if (queryAdd(slotIndex++, item, remainder, flags) == RETURNVALUE_NOERROR) { n += remainder; } } } } else { - std::shared_ptr<Item> destItem = getItemByIndex(index); + const auto &destItem = getItemByIndex(index); if (item->equals(destItem) && destItem->getItemCount() < destItem->getStackSize()) { n = destItem->getStackSize() - destItem->getItemCount(); } @@ -586,14 +615,14 @@ ReturnValue Container::queryMaxCount(int32_t index, const std::shared_ptr<Thing> return RETURNVALUE_NOERROR; } -ReturnValue Container::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor /*= nullptr */) { - int32_t index = getThingIndex(thing); +ReturnValue Container::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor /*= nullptr */) { + const int32_t index = getThingIndex(thing); if (index == -1) { g_logger().debug("{} - Failed to get thing index", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { g_logger().debug("{} - Item is nullptr", __FUNCTION__); return RETURNVALUE_NOTPOSSIBLE; @@ -608,24 +637,24 @@ ReturnValue Container::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t g_logger().debug("{} - Item is not movable", __FUNCTION__); return RETURNVALUE_NOTMOVABLE; } - std::shared_ptr<HouseTile> houseTile = std::dynamic_pointer_cast<HouseTile>(getTopParent()); + const std::shared_ptr<HouseTile> &houseTile = std::dynamic_pointer_cast<HouseTile>(getTopParent()); if (houseTile) { return houseTile->queryRemove(thing, count, flags, actor); } return RETURNVALUE_NOERROR; } -std::shared_ptr<Cylinder> Container::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) { +std::shared_ptr<Cylinder> Container::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) { if (!unlocked) { - *destItem = nullptr; + destItem = nullptr; return getContainer(); } if (index == 254 /*move up*/) { index = INDEX_WHEREEVER; - *destItem = nullptr; + destItem = nullptr; - std::shared_ptr<Container> parentContainer = std::dynamic_pointer_cast<Container>(getParent()); + const auto &parentContainer = std::dynamic_pointer_cast<Container>(getParent()); if (parentContainer) { return parentContainer; } @@ -634,7 +663,7 @@ std::shared_ptr<Cylinder> Container::queryDestination(int32_t &index, const std: if (index == 255 /*add wherever*/) { index = INDEX_WHEREEVER; - *destItem = nullptr; + destItem = nullptr; } else if (index >= static_cast<int32_t>(capacity()) && !hasPagination()) { /* if you have a container, maximize it to show all 20 slots @@ -644,39 +673,39 @@ std::shared_ptr<Cylinder> Container::queryDestination(int32_t &index, const std: the client calculates the slot position as if the bag has 20 slots */ index = INDEX_WHEREEVER; - *destItem = nullptr; + destItem = nullptr; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return getContainer(); } if (index != INDEX_WHEREEVER) { - std::shared_ptr<Item> itemFromIndex = getItemByIndex(index); + const auto &itemFromIndex = getItemByIndex(index); if (itemFromIndex) { - *destItem = itemFromIndex; + destItem = itemFromIndex; } - std::shared_ptr<Cylinder> subCylinder = std::dynamic_pointer_cast<Cylinder>(*destItem); + const auto &subCylinder = std::dynamic_pointer_cast<Cylinder>(destItem); if (subCylinder) { index = INDEX_WHEREEVER; - *destItem = nullptr; + destItem = nullptr; return subCylinder; } } - bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags); + const bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags); if (autoStack && item->isStackable() && item->getParent() != getContainer()) { - if (*destItem && (*destItem)->equals(item) && (*destItem)->getItemCount() < (*destItem)->getStackSize()) { + if (destItem && destItem->equals(item) && destItem->getItemCount() < destItem->getStackSize()) { return getContainer(); } // try find a suitable item to stack with uint32_t n = 0; - for (std::shared_ptr<Item> listItem : itemlist) { + for (const auto &listItem : itemlist) { if (listItem != item && listItem->equals(item) && listItem->getItemCount() < listItem->getStackSize()) { - *destItem = listItem; + destItem = listItem; index = n; return getContainer(); } @@ -686,11 +715,11 @@ std::shared_ptr<Cylinder> Container::queryDestination(int32_t &index, const std: return getContainer(); } -void Container::addThing(std::shared_ptr<Thing> thing) { +void Container::addThing(const std::shared_ptr<Thing> &thing) { return addThing(0, thing); } -void Container::addThing(int32_t index, std::shared_ptr<Thing> thing) { +void Container::addThing(int32_t index, const std::shared_ptr<Thing> &thing) { if (!thing) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -699,7 +728,7 @@ void Container::addThing(int32_t index, std::shared_ptr<Thing> thing) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -714,7 +743,7 @@ void Container::addThing(int32_t index, std::shared_ptr<Thing> thing) { } } -void Container::addItemBack(std::shared_ptr<Item> item) { +void Container::addItemBack(const std::shared_ptr<Item> &item) { addItem(item); updateItemWeight(item->getWeight()); @@ -724,13 +753,13 @@ void Container::addItemBack(std::shared_ptr<Item> item) { } } -void Container::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) { - int32_t index = getThingIndex(thing); +void Container::updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) { + const int32_t index = getThingIndex(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -746,13 +775,13 @@ void Container::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint3 } } -void Container::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { - std::shared_ptr<Item> item = thing->getItem(); +void Container::replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) { + const auto &item = thing->getItem(); if (!item) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> replacedItem = getItemByIndex(index); + const auto &replacedItem = getItemByIndex(index); if (!replacedItem) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -769,19 +798,19 @@ void Container::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { replacedItem->resetParent(); } -void Container::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { - std::shared_ptr<Item> item = thing->getItem(); +void Container::removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) { + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - int32_t index = getThingIndex(thing); + const int32_t index = getThingIndex(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } if (item->isStackable() && count != item->getItemCount()) { - uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count)); + const auto newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count)); const int32_t oldWeight = item->getWeight(); item->setItemCount(newCount); updateItemWeight(-oldWeight + item->getWeight()); @@ -803,9 +832,9 @@ void Container::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { } } -int32_t Container::getThingIndex(std::shared_ptr<Thing> thing) const { +int32_t Container::getThingIndex(const std::shared_ptr<Thing> &thing) const { int32_t index = 0; - for (std::shared_ptr<Item> item : itemlist) { + for (const std::shared_ptr<Item> &item : itemlist) { if (item == thing) { return index; } @@ -824,7 +853,7 @@ size_t Container::getLastIndex() const { uint32_t Container::getItemTypeCount(uint16_t itemId, int32_t subType /* = -1*/) const { uint32_t count = 0; - for (std::shared_ptr<Item> item : itemlist) { + for (const std::shared_ptr<Item> &item : itemlist) { if (item->getID() == itemId) { count += countByType(item, subType); } @@ -833,7 +862,7 @@ uint32_t Container::getItemTypeCount(uint16_t itemId, int32_t subType /* = -1*/) } std::map<uint32_t, uint32_t> &Container::getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const { - for (std::shared_ptr<Item> item : itemlist) { + for (const std::shared_ptr<Item> &item : itemlist) { countMap[item->getID()] += item->getItemCount(); } return countMap; @@ -850,15 +879,15 @@ ItemVector Container::getItems(bool recursive /*= false*/) { containerItems.push_back(*it); } } else { - for (std::shared_ptr<Item> item : itemlist) { + for (const std::shared_ptr<Item> &item : itemlist) { containerItems.push_back(item); } } return containerItems; } -void Container::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> topParent = getTopParent(); +void Container::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &topParent = getTopParent(); if (topParent->getCreature()) { topParent->postAddNotification(thing, oldParent, index, LINK_TOPPARENT); } else if (topParent == getContainer()) { @@ -871,8 +900,8 @@ void Container::postAddNotification(std::shared_ptr<Thing> thing, std::shared_pt } } -void Container::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> topParent = getTopParent(); +void Container::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &topParent = getTopParent(); if (topParent->getCreature()) { topParent->postRemoveNotification(thing, newParent, index, LINK_TOPPARENT); } else if (topParent == getContainer()) { @@ -885,16 +914,16 @@ void Container::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared } } -void Container::internalAddThing(std::shared_ptr<Thing> thing) { +void Container::internalAddThing(const std::shared_ptr<Thing> &thing) { internalAddThing(0, thing); } -void Container::internalAddThing(uint32_t, std::shared_ptr<Thing> thing) { +void Container::internalAddThing(uint32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return; } @@ -904,11 +933,11 @@ void Container::internalAddThing(uint32_t, std::shared_ptr<Thing> thing) { updateItemWeight(item->getWeight()); } -uint16_t Container::getFreeSlots() { +uint16_t Container::getFreeSlots() const { uint16_t counter = std::max<uint16_t>(0, capacity() - size()); - for (std::shared_ptr<Item> item : itemlist) { - if (std::shared_ptr<Container> container = item->getContainer()) { + for (const auto &item : itemlist) { + if (const auto &container = item->getContainer()) { counter += std::max<uint16_t>(0, container->getFreeSlots()); } } @@ -920,20 +949,20 @@ ContainerIterator Container::iterator() { return { getContainer(), static_cast<size_t>(g_configManager().getNumber(MAX_CONTAINER_DEPTH)) }; } -void Container::removeItem(std::shared_ptr<Thing> thing, bool sendUpdateToClient /* = false*/) { +void Container::removeItem(const std::shared_ptr<Thing> &thing, bool sendUpdateToClient /* = false*/) { if (thing == nullptr) { return; } - auto itemToRemove = thing->getItem(); + const auto &itemToRemove = thing->getItem(); if (itemToRemove == nullptr) { return; } - auto it = std::ranges::find(itemlist.begin(), itemlist.end(), itemToRemove); + const auto it = std::ranges::find(itemlist.begin(), itemlist.end(), itemToRemove); if (it != itemlist.end()) { // Send change to client - if (auto thingIndex = getThingIndex(thing); sendUpdateToClient && thingIndex != -1 && getParent()) { + if (const auto thingIndex = getThingIndex(thing); sendUpdateToClient && thingIndex != -1 && getParent()) { onRemoveContainerItem(thingIndex, itemToRemove); } @@ -1004,9 +1033,9 @@ void ContainerIterator::advance() { return; } - auto currentItem = container->itemlist[top.index]; + const auto ¤tItem = container->itemlist[top.index]; if (currentItem) { - auto subContainer = currentItem->getContainer(); + const auto &subContainer = currentItem->getContainer(); if (subContainer && !subContainer->itemlist.empty()) { size_t newDepth = top.depth + 1; if (newDepth <= maxTraversalDepth) { diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index e07b2edff3a..f7e1b5c42a3 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -134,27 +134,41 @@ class Container : public Item, public Cylinder { public: explicit Container(uint16_t type); Container(uint16_t type, uint16_t size, bool unlocked = true, bool pagination = false); - ~Container(); + ~Container() override; static std::shared_ptr<Container> create(uint16_t type); static std::shared_ptr<Container> create(uint16_t type, uint16_t size, bool unlocked = true, bool pagination = false); - static std::shared_ptr<Container> create(std::shared_ptr<Tile> type); + + /** + * @brief Creates a container for browse field functionality with items from a specified tile. + * + * This function generates a new container specifically for browse field use, + * populating it with items that meet certain criteria from the provided tile. Items + * that can be included must either have an internal container, be movable, or be + * wrapable without blocking path and without a unique ID. + * + * @param tile A shared pointer to the Tile from which items will be sourced. + * @return std::shared_ptr<Container> Returns a shared pointer to the newly created Container if successful; otherwise, returns nullptr. + * + * @note This function will return nullptr if the newContainer could not be created or if the tile pointer is null. + */ + static std::shared_ptr<Container> createBrowseField(const std::shared_ptr<Tile> &type); // non-copyable Container(const Container &) = delete; Container &operator=(const Container &) = delete; - std::shared_ptr<Item> clone() const override final; + std::shared_ptr<Item> clone() const final; - std::shared_ptr<Container> getContainer() override final { + std::shared_ptr<Container> getContainer() final { return static_self_cast<Container>(); } - std::shared_ptr<const Container> getContainer() const override final { + std::shared_ptr<const Container> getContainer() const final { return static_self_cast<Container>(); } - std::shared_ptr<Cylinder> getCylinder() override final { + std::shared_ptr<Cylinder> getCylinder() final { return getContainer(); } @@ -207,9 +221,9 @@ class Container : public Item, public Cylinder { return itemlist.rend(); } - bool countsToLootAnalyzerBalance(); + bool countsToLootAnalyzerBalance() const; bool hasParent(); - void addItem(std::shared_ptr<Item> item); + void addItem(const std::shared_ptr<Item> &item); StashContainerList getStowableItems() const; bool isStoreInbox() const; bool isStoreInboxFiltered() const; @@ -217,13 +231,13 @@ class Container : public Item, public Cylinder { std::vector<ContainerCategory_t> getStoreInboxValidCategories() const; std::shared_ptr<Item> getFilteredItemByIndex(size_t index) const; std::shared_ptr<Item> getItemByIndex(size_t index) const; - bool isHoldingItem(std::shared_ptr<Item> item); - bool isHoldingItemWithId(const uint16_t id); + bool isHoldingItem(const std::shared_ptr<Item> &item); + bool isHoldingItemWithId(uint16_t id); uint32_t getItemHoldingCount(); uint32_t getContainerHoldingCount(); - uint16_t getFreeSlots(); - uint32_t getWeight() const override final; + uint16_t getFreeSlots() const; + uint32_t getWeight() const final; bool isUnlocked() const { return !this->isCorpse() && unlocked; @@ -233,62 +247,62 @@ class Container : public Item, public Cylinder { } // cylinder implementations - virtual ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override final; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override final; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override final; + virtual ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) final; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) final; - void addThing(std::shared_ptr<Thing> thing) override final; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override final; - void addItemBack(std::shared_ptr<Item> item); + void addThing(const std::shared_ptr<Thing> &thing) final; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) final; + void addItemBack(const std::shared_ptr<Item> &item); - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override final; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override final; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) final; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) final; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override final; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) final; - int32_t getThingIndex(std::shared_ptr<Thing> thing) const override final; - size_t getFirstIndex() const override final; - size_t getLastIndex() const override final; - uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const override final; - std::map<uint32_t, uint32_t> &getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const override final; - std::shared_ptr<Thing> getThing(size_t index) const override final; + int32_t getThingIndex(const std::shared_ptr<Thing> &thing) const final; + size_t getFirstIndex() const final; + size_t getLastIndex() const final; + uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const final; + std::map<uint32_t, uint32_t> &getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const final; + std::shared_ptr<Thing> getThing(size_t index) const final; ItemVector getItems(bool recursive = false); - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void internalAddThing(std::shared_ptr<Thing> thing) override final; - void internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) override final; + void internalAddThing(const std::shared_ptr<Thing> &thing) final; + void internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) final; - virtual void removeItem(std::shared_ptr<Thing> thing, bool sendUpdateToClient = false); + virtual void removeItem(const std::shared_ptr<Thing> &thing, bool sendUpdateToClient = false); - uint32_t getOwnerId() const override final; + uint32_t getOwnerId() const final; bool isAnyKindOfRewardChest(); bool isAnyKindOfRewardContainer(); bool isBrowseFieldAndHoldsRewardChest(); - bool isInsideContainerWithId(const uint16_t id); + bool isInsideContainerWithId(uint16_t id); protected: std::ostringstream &getContentDescription(std::ostringstream &os, bool oldProtocol); - uint32_t m_maxItems; - uint32_t maxSize; - uint32_t totalWeight = 0; + uint32_t m_maxItems {}; + uint32_t maxSize {}; + uint32_t totalWeight {}; ItemDeque itemlist; - uint32_t serializationCount = 0; + uint32_t serializationCount = {}; - bool unlocked; - bool pagination; + bool unlocked {}; + bool pagination {}; friend class MapCache; private: - void onAddContainerItem(std::shared_ptr<Item> item); - void onUpdateContainerItem(uint32_t index, std::shared_ptr<Item> oldItem, std::shared_ptr<Item> newItem); - void onRemoveContainerItem(uint32_t index, std::shared_ptr<Item> item); + void onAddContainerItem(const std::shared_ptr<Item> &item); + void onUpdateContainerItem(uint32_t index, const std::shared_ptr<Item> &oldItem, const std::shared_ptr<Item> &newItem); + void onRemoveContainerItem(uint32_t index, const std::shared_ptr<Item> &item); std::shared_ptr<Container> getParentContainer(); std::shared_ptr<Container> getTopParentContainer(); diff --git a/src/items/containers/depot/depotchest.cpp b/src/items/containers/depot/depotchest.cpp index 2c7d21ed199..ea5a5d3897d 100644 --- a/src/items/containers/depot/depotchest.cpp +++ b/src/items/containers/depot/depotchest.cpp @@ -8,6 +8,7 @@ */ #include "items/containers/depot/depotchest.hpp" + #include "utils/tools.hpp" DepotChest::DepotChest(uint16_t type) : @@ -17,8 +18,8 @@ DepotChest::DepotChest(uint16_t type) : pagination = true; } -ReturnValue DepotChest::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor /* = nullptr*/) { - std::shared_ptr<Item> item = thing->getItem(); +ReturnValue DepotChest::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor /* = nullptr*/) { + const auto &item = thing->getItem(); if (item == nullptr) { return RETURNVALUE_NOTPOSSIBLE; } @@ -26,7 +27,7 @@ ReturnValue DepotChest::queryAdd(int32_t index, const std::shared_ptr<Thing> &th return RETURNVALUE_ITEMISNOTYOURS; } - bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); + const bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); if (!skipLimit) { int32_t addCount = 0; @@ -35,14 +36,14 @@ ReturnValue DepotChest::queryAdd(int32_t index, const std::shared_ptr<Thing> &th } if (item->getTopParent().get() != this) { - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const std::shared_ptr<Container> &container = item->getContainer()) { addCount = container->getItemHoldingCount() + 1; } else { addCount = 1; } } - if (std::shared_ptr<Cylinder> localParent = getRealParent()) { + if (const std::shared_ptr<Cylinder> &localParent = getRealParent()) { if (localParent->getContainer()->getItemHoldingCount() + addCount > maxDepotItems) { return RETURNVALUE_DEPOTISFULL; } @@ -54,22 +55,22 @@ ReturnValue DepotChest::queryAdd(int32_t index, const std::shared_ptr<Thing> &th return Container::queryAdd(index, thing, count, flags, actor); } -void DepotChest::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void DepotChest::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postAddNotification(thing, oldParent, index, LINK_PARENT); } } -void DepotChest::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void DepotChest::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postRemoveNotification(thing, newParent, index, LINK_PARENT); } } std::shared_ptr<Cylinder> DepotChest::getParent() { - auto parentLocked = m_parent.lock(); + const auto &parentLocked = m_parent.lock(); if (parentLocked && parentLocked->getParent()) { return parentLocked->getParent()->getParent(); } diff --git a/src/items/containers/depot/depotchest.hpp b/src/items/containers/depot/depotchest.hpp index 6b64ca2b897..7b357540d8a 100644 --- a/src/items/containers/depot/depotchest.hpp +++ b/src/items/containers/depot/depotchest.hpp @@ -21,10 +21,10 @@ class DepotChest final : public Container { } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; bool isDepotChest() const override { return true; diff --git a/src/items/containers/depot/depotlocker.cpp b/src/items/containers/depot/depotlocker.cpp index c7320293efd..c5da2beaad6 100644 --- a/src/items/containers/depot/depotlocker.cpp +++ b/src/items/containers/depot/depotlocker.cpp @@ -22,26 +22,26 @@ Attr_ReadValue DepotLocker::readAttr(AttrTypes_t attr, PropStream &propStream) { return Item::readAttr(attr, propStream); } -ReturnValue DepotLocker::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature>) { +ReturnValue DepotLocker::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> &) { return RETURNVALUE_NOTENOUGHROOM; } -void DepotLocker::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - auto parentLocked = m_parent.lock(); +void DepotLocker::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const auto &parentLocked = m_parent.lock(); if (parentLocked) { parentLocked->postAddNotification(thing, oldParent, index, LINK_PARENT); } } -void DepotLocker::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - auto parentLocked = m_parent.lock(); +void DepotLocker::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const auto &parentLocked = m_parent.lock(); if (parentLocked) { parentLocked->postRemoveNotification(thing, newParent, index, LINK_PARENT); } } -void DepotLocker::removeInbox(std::shared_ptr<Inbox> inbox) { - auto cit = std::find(itemlist.begin(), itemlist.end(), inbox); +void DepotLocker::removeInbox(const std::shared_ptr<Inbox> &inbox) { + const auto cit = std::ranges::find(itemlist, inbox); if (cit == itemlist.end()) { return; } diff --git a/src/items/containers/depot/depotlocker.hpp b/src/items/containers/depot/depotlocker.hpp index 09d794c444f..a4b2a3f48bf 100644 --- a/src/items/containers/depot/depotlocker.hpp +++ b/src/items/containers/depot/depotlocker.hpp @@ -20,7 +20,7 @@ class DepotLocker final : public Container { return static_self_cast<DepotLocker>(); } - void removeInbox(std::shared_ptr<Inbox> inbox); + void removeInbox(const std::shared_ptr<Inbox> &inbox); // serialization Attr_ReadValue readAttr(AttrTypes_t attr, PropStream &propStream) override; @@ -33,10 +33,10 @@ class DepotLocker final : public Container { } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; bool canRemove() const override { return false; diff --git a/src/items/containers/inbox/inbox.cpp b/src/items/containers/inbox/inbox.cpp index 220f119645f..92b113f19cc 100644 --- a/src/items/containers/inbox/inbox.cpp +++ b/src/items/containers/inbox/inbox.cpp @@ -8,6 +8,7 @@ */ #include "items/containers/inbox/inbox.hpp" + #include "utils/tools.hpp" Inbox::Inbox(uint16_t type) : @@ -15,14 +16,14 @@ Inbox::Inbox(uint16_t type) : maxInboxItems = std::numeric_limits<uint16_t>::max(); } -ReturnValue Inbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t flags, std::shared_ptr<Creature>) { +ReturnValue Inbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t flags, const std::shared_ptr<Creature> &) { int32_t addCount = 0; if (!hasBitSet(FLAG_NOLIMIT, flags)) { return RETURNVALUE_CONTAINERNOTENOUGHROOM; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return RETURNVALUE_NOTPOSSIBLE; } @@ -36,7 +37,7 @@ ReturnValue Inbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32 } if (item->getTopParent().get() != this) { // MY - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const std::shared_ptr<Container> &container = item->getContainer()) { addCount = container->getItemHoldingCount() + 1; } else { addCount = 1; @@ -50,22 +51,22 @@ ReturnValue Inbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32 return RETURNVALUE_NOERROR; } -void Inbox::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void Inbox::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postAddNotification(thing, oldParent, index, LINK_PARENT); } } -void Inbox::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void Inbox::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postRemoveNotification(thing, newParent, index, LINK_PARENT); } } std::shared_ptr<Cylinder> Inbox::getParent() { - auto parentLocked = m_parent.lock(); + const auto &parentLocked = m_parent.lock(); if (parentLocked) { return parentLocked->getParent(); } diff --git a/src/items/containers/inbox/inbox.hpp b/src/items/containers/inbox/inbox.hpp index 79eb126edc8..731920f1ded 100644 --- a/src/items/containers/inbox/inbox.hpp +++ b/src/items/containers/inbox/inbox.hpp @@ -20,10 +20,10 @@ class Inbox final : public Container { } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; bool isInbox() const override { return true; diff --git a/src/items/containers/mailbox/mailbox.cpp b/src/items/containers/mailbox/mailbox.cpp index c558b85e30d..27562e92d7e 100644 --- a/src/items/containers/mailbox/mailbox.cpp +++ b/src/items/containers/mailbox/mailbox.cpp @@ -8,13 +8,15 @@ */ #include "items/containers/mailbox/mailbox.hpp" + +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "io/iologindata.hpp" #include "game/scheduling/save_manager.hpp" +#include "items/containers/inbox/inbox.hpp" #include "map/spectators.hpp" -ReturnValue Mailbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, std::shared_ptr<Creature>) { - std::shared_ptr<Item> item = thing->getItem(); +ReturnValue Mailbox::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, const std::shared_ptr<Creature> &) { + const auto &item = thing->getItem(); if (item && Mailbox::canSend(item)) { return RETURNVALUE_NOERROR; } @@ -26,50 +28,50 @@ ReturnValue Mailbox::queryMaxCount(int32_t, const std::shared_ptr<Thing> &, uint return RETURNVALUE_NOERROR; } -ReturnValue Mailbox::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> /*= nullptr */) { +ReturnValue Mailbox::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> & /*= nullptr */) { return RETURNVALUE_NOTPOSSIBLE; } -std::shared_ptr<Cylinder> Mailbox::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item>*, uint32_t &) { +std::shared_ptr<Cylinder> Mailbox::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item> &, uint32_t &) { return getMailbox(); } -void Mailbox::addThing(std::shared_ptr<Thing> thing) { +void Mailbox::addThing(const std::shared_ptr<Thing> &thing) { return addThing(0, thing); } -void Mailbox::addThing(int32_t, std::shared_ptr<Thing> thing) { +void Mailbox::addThing(int32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item && Mailbox::canSend(item)) { sendItem(item); } } -void Mailbox::updateThing(std::shared_ptr<Thing>, uint16_t, uint32_t) { +void Mailbox::updateThing(const std::shared_ptr<Thing> &, uint16_t, uint32_t) { // } -void Mailbox::replaceThing(uint32_t, std::shared_ptr<Thing>) { +void Mailbox::replaceThing(uint32_t, const std::shared_ptr<Thing> &) { // } -void Mailbox::removeThing(std::shared_ptr<Thing>, uint32_t) { +void Mailbox::removeThing(const std::shared_ptr<Thing> &, uint32_t) { // } -void Mailbox::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { +void Mailbox::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); } -void Mailbox::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { +void Mailbox::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); } -bool Mailbox::sendItem(std::shared_ptr<Item> item) const { +bool Mailbox::sendItem(const std::shared_ptr<Item> &item) const { std::string receiver; if (!getReceiver(item, receiver)) { return false; @@ -86,9 +88,9 @@ bool Mailbox::sendItem(std::shared_ptr<Item> item) const { } } - std::shared_ptr<Player> player = g_game().getPlayerByName(receiver, true); + const auto &player = g_game().getPlayerByName(receiver, true); std::string writer; - time_t date = time(0); + time_t date = getTimeNow(); std::string text; if (item && item->getID() == ITEM_LETTER && !item->getAttribute<std::string>(ItemAttribute_t::WRITER).empty()) { writer = item->getAttribute<std::string>(ItemAttribute_t::WRITER); @@ -96,9 +98,11 @@ bool Mailbox::sendItem(std::shared_ptr<Item> item) const { text = item->getAttribute<std::string>(ItemAttribute_t::TEXT); } if (player && item) { - if (g_game().internalMoveItem(item->getParent(), player->getInbox(), INDEX_WHEREEVER, item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) { - auto newItem = g_game().transformItem(item, item->getID() + 1); - if (newItem && newItem->getID() == ITEM_LETTER_STAMPED && writer != "") { + const auto &playerInbox = player->getInbox(); + const auto &itemParent = item->getParent(); + if (g_game().internalMoveItem(itemParent, playerInbox, INDEX_WHEREEVER, item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) { + const auto &newItem = g_game().transformItem(item, item->getID() + 1); + if (newItem && newItem->getID() == ITEM_LETTER_STAMPED && !writer.empty()) { newItem->setAttribute(ItemAttribute_t::WRITER, writer); newItem->setAttribute(ItemAttribute_t::DATE, date); newItem->setAttribute(ItemAttribute_t::TEXT, text); @@ -114,10 +118,10 @@ bool Mailbox::sendItem(std::shared_ptr<Item> item) const { return false; } -bool Mailbox::getReceiver(std::shared_ptr<Item> item, std::string &name) const { - std::shared_ptr<Container> container = item->getContainer(); +bool Mailbox::getReceiver(const std::shared_ptr<Item> &item, std::string &name) const { + const std::shared_ptr<Container> &container = item->getContainer(); if (container) { - for (std::shared_ptr<Item> containerItem : container->getItemList()) { + for (const std::shared_ptr<Item> &containerItem : container->getItemList()) { if (containerItem->getID() == ITEM_LABEL && getReceiver(containerItem, name)) { return true; } @@ -135,6 +139,6 @@ bool Mailbox::getReceiver(std::shared_ptr<Item> item, std::string &name) const { return true; } -bool Mailbox::canSend(std::shared_ptr<Item> item) { +bool Mailbox::canSend(const std::shared_ptr<Item> &item) { return !item->hasOwner() && (item->getID() == ITEM_PARCEL || item->getID() == ITEM_LETTER); } diff --git a/src/items/containers/mailbox/mailbox.hpp b/src/items/containers/mailbox/mailbox.hpp index 116cd0ee1c4..8891c00339e 100644 --- a/src/items/containers/mailbox/mailbox.hpp +++ b/src/items/containers/mailbox/mailbox.hpp @@ -21,30 +21,30 @@ class Mailbox final : public Item, public Cylinder { return static_self_cast<Mailbox>(); } - std::shared_ptr<Cylinder> getCylinder() override final { + std::shared_ptr<Cylinder> getCylinder() override { return getMailbox(); } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; - void addThing(std::shared_ptr<Thing> thing) override; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; + void addThing(const std::shared_ptr<Thing> &thing) override; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) override; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; private: - bool getReceiver(std::shared_ptr<Item> item, std::string &name) const; - bool sendItem(std::shared_ptr<Item> item) const; + bool getReceiver(const std::shared_ptr<Item> &item, std::string &name) const; + bool sendItem(const std::shared_ptr<Item> &item) const; - static bool canSend(std::shared_ptr<Item> item); + static bool canSend(const std::shared_ptr<Item> &item); }; diff --git a/src/items/containers/rewards/reward.cpp b/src/items/containers/rewards/reward.cpp index 6a8374e8060..f3e4313542d 100644 --- a/src/items/containers/rewards/reward.cpp +++ b/src/items/containers/rewards/reward.cpp @@ -16,12 +16,12 @@ Reward::Reward() : pagination = true; } -ReturnValue Reward::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, std::shared_ptr<Creature> actor /* = nullptr*/) { - if (actor) { +ReturnValue Reward::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, const std::shared_ptr<Creature> &actor /* = nullptr*/) { + if (actor || !thing) { return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return RETURNVALUE_NOTPOSSIBLE; } @@ -37,15 +37,15 @@ ReturnValue Reward::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint3 return RETURNVALUE_NOERROR; } -void Reward::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void Reward::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postAddNotification(thing, oldParent, index, LINK_PARENT); } } -void Reward::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - std::shared_ptr<Cylinder> localParent = getParent(); +void Reward::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const std::shared_ptr<Cylinder> &localParent = getParent(); if (localParent != nullptr) { localParent->postRemoveNotification(thing, newParent, index, LINK_PARENT); } diff --git a/src/items/containers/rewards/reward.hpp b/src/items/containers/rewards/reward.hpp index 1ab3c8f9b70..afdcd1c0d5f 100644 --- a/src/items/containers/rewards/reward.hpp +++ b/src/items/containers/rewards/reward.hpp @@ -11,27 +11,27 @@ #include "items/containers/container.hpp" -class Reward : public Container { +class Reward final : public Container { public: explicit Reward(); - std::shared_ptr<Reward> getReward() final { + std::shared_ptr<Reward> getReward() override { return static_self_cast<Reward>(); } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) final; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; // overrides - bool canRemove() const final { + bool canRemove() const override { return true; } - std::shared_ptr<Cylinder> getParent() final; - std::shared_ptr<Cylinder> getRealParent() final { + std::shared_ptr<Cylinder> getParent() override; + std::shared_ptr<Cylinder> getRealParent() override { return m_parent.lock(); } }; diff --git a/src/items/containers/rewards/rewardchest.cpp b/src/items/containers/rewards/rewardchest.cpp index 96cf9c2edcc..32019b0ce75 100644 --- a/src/items/containers/rewards/rewardchest.cpp +++ b/src/items/containers/rewards/rewardchest.cpp @@ -16,7 +16,7 @@ RewardChest::RewardChest(uint16_t type) : pagination = true; } -ReturnValue RewardChest::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> actor /* = nullptr*/) { +ReturnValue RewardChest::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> &actor /* = nullptr*/) { if (actor) { return RETURNVALUE_NOTPOSSIBLE; } @@ -24,32 +24,32 @@ ReturnValue RewardChest::queryAdd(int32_t, const std::shared_ptr<Thing> &, uint3 return RETURNVALUE_NOERROR; } -void RewardChest::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { - auto parentLocked = m_parent.lock(); +void RewardChest::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { + const auto &parentLocked = m_parent.lock(); if (parentLocked) { parentLocked->postAddNotification(thing, oldParent, index, LINK_PARENT); } } -void RewardChest::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { - auto parentLocked = m_parent.lock(); +void RewardChest::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + const auto &parentLocked = m_parent.lock(); if (parentLocked) { parentLocked->postRemoveNotification(thing, newParent, index, LINK_PARENT); } } // Second argument is disabled by default because not need to send to client in the RewardChest -void RewardChest::removeItem(std::shared_ptr<Thing> thing, bool /* sendToClient = false*/) { +void RewardChest::removeItem(const std::shared_ptr<Thing> &thing, bool /* sendToClient = false*/) { if (thing == nullptr) { return; } - auto itemToRemove = thing->getItem(); + const auto &itemToRemove = thing->getItem(); if (itemToRemove == nullptr) { return; } - auto it = std::ranges::find(itemlist.begin(), itemlist.end(), itemToRemove); + const auto it = std::ranges::find(itemlist.begin(), itemlist.end(), itemToRemove); if (it != itemlist.end()) { itemlist.erase(it); itemToRemove->resetParent(); diff --git a/src/items/containers/rewards/rewardchest.hpp b/src/items/containers/rewards/rewardchest.hpp index 2960128eb75..6c66865699b 100644 --- a/src/items/containers/rewards/rewardchest.hpp +++ b/src/items/containers/rewards/rewardchest.hpp @@ -15,19 +15,19 @@ class RewardChest final : public Container { public: explicit RewardChest(uint16_t type); - std::shared_ptr<RewardChest> getRewardChest() final { + std::shared_ptr<RewardChest> getRewardChest() override { return static_self_cast<RewardChest>(); } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) final; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - bool canRemove() const final { + bool canRemove() const override { return false; } - void removeItem(std::shared_ptr<Thing> thing, bool sendToClient = false) override; + void removeItem(const std::shared_ptr<Thing> &thing, bool sendToClient = false) override; }; diff --git a/src/items/cylinder.cpp b/src/items/cylinder.cpp index fa61eab2fcb..4a4acbdf108 100644 --- a/src/items/cylinder.cpp +++ b/src/items/cylinder.cpp @@ -11,7 +11,7 @@ std::shared_ptr<VirtualCylinder> VirtualCylinder::virtualCylinder = std::make_shared<VirtualCylinder>(); -int32_t Cylinder::getThingIndex(std::shared_ptr<Thing>) const { +int32_t Cylinder::getThingIndex(const std::shared_ptr<Thing> &) const { return -1; } @@ -35,11 +35,11 @@ std::shared_ptr<Thing> Cylinder::getThing(size_t) const { return nullptr; } -void Cylinder::internalAddThing(std::shared_ptr<Thing>) { +void Cylinder::internalAddThing(const std::shared_ptr<Thing> &) { // } -void Cylinder::internalAddThing(uint32_t, std::shared_ptr<Thing>) { +void Cylinder::internalAddThing(uint32_t, const std::shared_ptr<Thing> &) { // } diff --git a/src/items/cylinder.hpp b/src/items/cylinder.hpp index f6c149dd589..c858d398620 100644 --- a/src/items/cylinder.hpp +++ b/src/items/cylinder.hpp @@ -9,7 +9,7 @@ #pragma once -#include "declarations.hpp" +#include "items/items_definitions.hpp" #include "items/thing.hpp" class Item; @@ -30,7 +30,7 @@ class Cylinder : virtual public Thing { * \param actor the creature trying to add the thing * \returns ReturnValue holds the return value */ - virtual ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) = 0; + virtual ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) = 0; /** * Query the cylinder how much it can accept @@ -51,7 +51,7 @@ class Cylinder : virtual public Thing { * \param flags optional flags to modify the default behaviour * \returns ReturnValue holds the return value */ - virtual ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> = nullptr) = 0; + virtual ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) = 0; /** * Query the destination cylinder @@ -63,20 +63,20 @@ class Cylinder : virtual public Thing { * this method can modify the flags * \returns Cylinder returns the destination cylinder */ - virtual std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) = 0; + virtual std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) = 0; /** * Add the object to the cylinder * \param thing is the object to add */ - virtual void addThing(std::shared_ptr<Thing> thing) = 0; + virtual void addThing(const std::shared_ptr<Thing> &thing) = 0; /** * Add the object to the cylinder * \param index points to the destination index (inventory slot/container position) * \param thing is the object to add */ - virtual void addThing(int32_t index, std::shared_ptr<Thing> thing) = 0; + virtual void addThing(int32_t index, const std::shared_ptr<Thing> &thing) = 0; /** * Update the item count or type for an object @@ -84,21 +84,21 @@ class Cylinder : virtual public Thing { * \param itemId is the new item id * \param count is the new count value */ - virtual void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) = 0; + virtual void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) = 0; /** * Replace an object with a new * \param index is the position to change (inventory slot/container position) * \param thing is the object to update */ - virtual void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) = 0; + virtual void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) = 0; /** * Remove an object * \param thing is the object to delete * \param count is the new count value */ - virtual void removeThing(std::shared_ptr<Thing> thing, uint32_t count) = 0; + virtual void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) = 0; /** * Is sent after an operation (move/add) to update internal values @@ -106,7 +106,7 @@ class Cylinder : virtual public Thing { * \param index is the objects new index value * \param link holds the relation the object has to the cylinder */ - virtual void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) = 0; + virtual void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, const CylinderLink_t link = LINK_OWNER) = 0; /** * Is sent after an operation (move/remove) to update internal values @@ -114,14 +114,14 @@ class Cylinder : virtual public Thing { * \param index is the previous index of the removed object * \param link holds the relation the object has to the cylinder */ - virtual void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) = 0; + virtual void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) = 0; /** * Gets the index of an object * \param thing the object to get the index value from * \returns the index of the object, returns -1 if not found */ - virtual int32_t getThingIndex(std::shared_ptr<Thing> thing) const; + virtual int32_t getThingIndex(const std::shared_ptr<Thing> &thing) const; /** * Returns the first index @@ -160,14 +160,14 @@ class Cylinder : virtual public Thing { * Adds an object to the cylinder without sending to the client(s) * \param thing is the object to add */ - virtual void internalAddThing(std::shared_ptr<Thing> thing); + virtual void internalAddThing(const std::shared_ptr<Thing> &thing); /** * Adds an object to the cylinder without sending to the client(s) * \param thing is the object to add * \param index points to the destination index (inventory slot/container position) */ - virtual void internalAddThing(uint32_t index, std::shared_ptr<Thing> thing); + virtual void internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing); virtual void startDecaying(); }; @@ -176,27 +176,27 @@ class VirtualCylinder final : public Cylinder { public: static std::shared_ptr<VirtualCylinder> virtualCylinder; - virtual ReturnValue queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> = nullptr) override { + virtual ReturnValue queryAdd(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> & = nullptr) override { return RETURNVALUE_NOTPOSSIBLE; } virtual ReturnValue queryMaxCount(int32_t, const std::shared_ptr<Thing> &, uint32_t, uint32_t &, uint32_t) override { return RETURNVALUE_NOTPOSSIBLE; } - virtual ReturnValue queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> = nullptr) override { + virtual ReturnValue queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> &actor = nullptr) override { return RETURNVALUE_NOTPOSSIBLE; } - virtual std::shared_ptr<Cylinder> queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item>*, uint32_t &) override { + virtual std::shared_ptr<Cylinder> queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item> &, uint32_t &) override { return nullptr; } - virtual void addThing(std::shared_ptr<Thing>) override { } - virtual void addThing(int32_t, std::shared_ptr<Thing>) override { } - virtual void updateThing(std::shared_ptr<Thing>, uint16_t, uint32_t) override { } - virtual void replaceThing(uint32_t, std::shared_ptr<Thing>) override { } - virtual void removeThing(std::shared_ptr<Thing>, uint32_t) override { } + virtual void addThing(const std::shared_ptr<Thing> &) override { } + virtual void addThing(int32_t, const std::shared_ptr<Thing> &) override { } + virtual void updateThing(const std::shared_ptr<Thing> &, uint16_t, uint32_t) override { } + virtual void replaceThing(uint32_t, const std::shared_ptr<Thing> &) override { } + virtual void removeThing(const std::shared_ptr<Thing> &, uint32_t) override { } - virtual void postAddNotification(std::shared_ptr<Thing>, std::shared_ptr<Cylinder>, int32_t, CylinderLink_t = LINK_OWNER) override { } - virtual void postRemoveNotification(std::shared_ptr<Thing>, std::shared_ptr<Cylinder>, int32_t, CylinderLink_t = LINK_OWNER) override { } + virtual void postAddNotification(const std::shared_ptr<Thing> &, const std::shared_ptr<Cylinder> &, int32_t, CylinderLink_t = LINK_OWNER) override { } + virtual void postRemoveNotification(const std::shared_ptr<Thing> &, const std::shared_ptr<Cylinder> &, int32_t, CylinderLink_t = LINK_OWNER) override { } bool isPushable() override { return false; diff --git a/src/items/decay/decay.cpp b/src/items/decay/decay.cpp index 58bd6095340..5421340d9ad 100644 --- a/src/items/decay/decay.cpp +++ b/src/items/decay/decay.cpp @@ -9,9 +9,10 @@ #include "items/decay/decay.hpp" -#include "lib/di/container.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" +#include "lib/di/container.hpp" Decay &Decay::getInstance() { return inject<Decay>(); @@ -45,7 +46,7 @@ void Decay::startDecay(const std::shared_ptr<Item> &item) { stopDecay(item); } - int64_t timestamp = OTSYS_TIME() + duration; + const int64_t timestamp = OTSYS_TIME() + duration; if (decayMap.empty()) { eventId = g_dispatcher().scheduleEvent( std::max<int32_t>(SCHEDULER_MINTICKS, duration), [this] { checkDecay(); }, "Decay::checkDecay" @@ -70,13 +71,14 @@ void Decay::stopDecay(const std::shared_ptr<Item> &item) { return; } if (item->hasAttribute(ItemAttribute_t::DECAYSTATE)) { - auto timestamp = item->getAttribute<int64_t>(ItemAttribute_t::DURATION_TIMESTAMP); + const auto timestamp = item->getAttribute<int64_t>(ItemAttribute_t::DURATION_TIMESTAMP); if (item->hasAttribute(ItemAttribute_t::DURATION_TIMESTAMP)) { - auto it = decayMap.find(timestamp); + const auto it = decayMap.find(timestamp); if (it != decayMap.end()) { auto &decayItems = it->second; - size_t i = 0, end = decayItems.size(); + size_t i = 0; + const size_t end = decayItems.size(); auto decayItem = decayItems[i]; if (end == 1) { if (item == decayItem) { @@ -114,12 +116,13 @@ void Decay::stopDecay(const std::shared_ptr<Item> &item) { } void Decay::checkDecay() { - int64_t timestamp = OTSYS_TIME(); + const int64_t timestamp = OTSYS_TIME(); std::vector<std::shared_ptr<Item>> tempItems; tempItems.reserve(32); // Small preallocation - auto it = decayMap.begin(), end = decayMap.end(); + auto it = decayMap.begin(); + const auto end = decayMap.end(); while (it != end) { if (it->first > timestamp) { break; @@ -129,7 +132,7 @@ void Decay::checkDecay() { auto &decayItems = it->second; tempItems.reserve(tempItems.size() + decayItems.size()); for (auto &decayItem : decayItems) { - tempItems.push_back(decayItem); + tempItems.emplace_back(decayItem); } it = decayMap.erase(it); } @@ -160,7 +163,7 @@ void Decay::internalDecayItem(const std::shared_ptr<Item> &item) { // Remove the item and halt the decay process if a player triggers a bug where the item's decay ID matches its equip or de-equip transformation ID if (it.id == it.transformEquipTo || it.id == it.transformDeEquipTo) { g_game().internalRemoveItem(item); - auto player = item->getHoldingPlayer(); + const auto &player = item->getHoldingPlayer(); if (player) { g_logger().error("[{}] - internalDecayItem failed to player {}, item id is same from transform equip/deequip, " " item id: {}, equip to id: '{}', deequip to id '{}'", @@ -170,7 +173,7 @@ void Decay::internalDecayItem(const std::shared_ptr<Item> &item) { } if (it.decayTo != 0) { - std::shared_ptr<Player> player = item->getHoldingPlayer(); + const auto &player = item->getHoldingPlayer(); if (player) { bool needUpdateSkills = false; for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { diff --git a/src/items/decay/decay.hpp b/src/items/decay/decay.hpp index cce3b8b78d5..2a91b36018a 100644 --- a/src/items/decay/decay.hpp +++ b/src/items/decay/decay.hpp @@ -25,7 +25,7 @@ class Decay { private: void checkDecay(); - void internalDecayItem(const std::shared_ptr<Item> &item); + static void internalDecayItem(const std::shared_ptr<Item> &item); uint32_t eventId { 0 }; // order is important, so we use an std::map diff --git a/src/items/functions/item/attribute.cpp b/src/items/functions/item/attribute.cpp index 747b8c90c39..3c205f83ae6 100644 --- a/src/items/functions/item/attribute.cpp +++ b/src/items/functions/item/attribute.cpp @@ -9,6 +9,8 @@ #include "items/functions/item/attribute.hpp" +#include "utils/tools.hpp" + /* ============================= * ItemAttribute class (Attributes methods) @@ -20,12 +22,12 @@ const std::string &ItemAttribute::getAttributeString(ItemAttribute_t type) const return emptyString; } - auto attribute = getAttribute(type); + const auto attribute = getAttribute(type); if (!attribute) { return emptyString; } - return *attribute->getString().get(); + return *attribute->getString(); } const int64_t &ItemAttribute::getAttributeValue(ItemAttribute_t type) const { @@ -34,7 +36,7 @@ const int64_t &ItemAttribute::getAttributeValue(ItemAttribute_t type) const { return emptyInt; } - auto attribute = getAttribute(type); + const auto attribute = getAttribute(type); if (!attribute) { return emptyInt; } @@ -117,22 +119,22 @@ const CustomAttribute* ItemAttribute::getCustomAttribute(const std::string &attr } void ItemAttribute::setCustomAttribute(const std::string &key, const int64_t value) { - CustomAttribute attribute(key, value); + const CustomAttribute attribute(key, value); customAttributeMap[asLowerCaseString(key)] = attribute; } void ItemAttribute::setCustomAttribute(const std::string &key, const std::string &value) { - CustomAttribute attribute(key, value); + const CustomAttribute attribute(key, value); customAttributeMap[asLowerCaseString(key)] = attribute; } void ItemAttribute::setCustomAttribute(const std::string &key, const double value) { - CustomAttribute attribute(key, value); + const CustomAttribute attribute(key, value); customAttributeMap[asLowerCaseString(key)] = attribute; } void ItemAttribute::setCustomAttribute(const std::string &key, const bool value) { - CustomAttribute attribute(key, value); + const CustomAttribute attribute(key, value); customAttributeMap[asLowerCaseString(key)] = attribute; } @@ -141,7 +143,7 @@ void ItemAttribute::addCustomAttribute(const std::string &key, const CustomAttri } bool ItemAttribute::removeCustomAttribute(const std::string &attributeName) { - auto it = customAttributeMap.find(asLowerCaseString(attributeName)); + const auto it = customAttributeMap.find(asLowerCaseString(attributeName)); if (it == customAttributeMap.end()) { return false; } diff --git a/src/items/functions/item/attribute.hpp b/src/items/functions/item/attribute.hpp index a2d3ba128ed..3d99187d93a 100644 --- a/src/items/functions/item/attribute.hpp +++ b/src/items/functions/item/attribute.hpp @@ -11,11 +11,10 @@ #include "enums/item_attribute.hpp" #include "items/functions/item/custom_attribute.hpp" -#include "utils/tools.hpp" class ItemAttributeHelper { public: - bool isAttributeInteger(ItemAttribute_t type) const { + static bool isAttributeInteger(ItemAttribute_t type) { switch (type) { case ItemAttribute_t::STORE: case ItemAttribute_t::ACTIONID: @@ -48,7 +47,7 @@ class ItemAttributeHelper { } } - bool isAttributeString(ItemAttribute_t type) const { + static bool isAttributeString(ItemAttribute_t type) { switch (type) { case ItemAttribute_t::DESCRIPTION: case ItemAttribute_t::TEXT: @@ -88,10 +87,9 @@ class Attributes : public ItemAttributeHelper { } std::variant<int64_t, std::shared_ptr<std::string>> getDefaultValueForType(ItemAttribute_t attributeType) const { - ItemAttributeHelper helper; - if (helper.isAttributeInteger(attributeType)) { + if (ItemAttributeHelper::isAttributeInteger(attributeType)) { return 0; - } else if (helper.isAttributeString(attributeType)) { + } else if (ItemAttributeHelper::isAttributeString(attributeType)) { return std::make_shared<std::string>(); } else { return {}; @@ -116,7 +114,7 @@ class Attributes : public ItemAttributeHelper { return emptyValue; } - const std::shared_ptr<std::string> getString() const { + std::shared_ptr<std::string> getString() const { if (std::holds_alternative<std::shared_ptr<std::string>>(value)) { return std::get<std::shared_ptr<std::string>>(value); } @@ -138,10 +136,10 @@ class ItemAttribute : public ItemAttributeHelper { // CustomAttribute object methods const CustomAttribute* getCustomAttribute(const std::string &attributeName) const; - void setCustomAttribute(const std::string &key, const int64_t value); + void setCustomAttribute(const std::string &key, int64_t value); void setCustomAttribute(const std::string &key, const std::string &value); - void setCustomAttribute(const std::string &key, const double value); - void setCustomAttribute(const std::string &key, const bool value); + void setCustomAttribute(const std::string &key, double value); + void setCustomAttribute(const std::string &key, bool value); void addCustomAttribute(const std::string &key, const CustomAttribute &customAttribute); bool removeCustomAttribute(const std::string &attributeName); @@ -158,12 +156,9 @@ class ItemAttribute : public ItemAttributeHelper { } bool hasAttribute(ItemAttribute_t type) const { - for (const auto &attr : attributeVector) { - if (attr.getAttributeType() == type) { - return true; - } - } - return false; + return std::ranges::any_of(attributeVector, [type](const auto &attr) { + return attr.getAttributeType() == type; + }); } const Attributes* getAttribute(ItemAttribute_t type) const; diff --git a/src/items/functions/item/custom_attribute.cpp b/src/items/functions/item/custom_attribute.cpp index 462ba4b520a..ffe479307ff 100644 --- a/src/items/functions/item/custom_attribute.cpp +++ b/src/items/functions/item/custom_attribute.cpp @@ -15,20 +15,20 @@ CustomAttribute::CustomAttribute() = default; CustomAttribute::~CustomAttribute() = default; // Constructor for int64_t -CustomAttribute::CustomAttribute(const std::string &initStringKey, const int64_t initInt64) : - stringKey(initStringKey), value(initInt64) { +CustomAttribute::CustomAttribute(std::string initStringKey, const int64_t initInt64) : + stringKey(std::move(initStringKey)), value(initInt64) { } // Constructor for string -CustomAttribute::CustomAttribute(const std::string &initStringKey, const std::string &initStringValue) : - stringKey(initStringKey), value(initStringValue) { +CustomAttribute::CustomAttribute(std::string initStringKey, const std::string &initStringValue) : + stringKey(std::move(initStringKey)), value(initStringValue) { } // Constructor for double -CustomAttribute::CustomAttribute(const std::string &initStringKey, const double initDoubleValue) : - stringKey(initStringKey), value(initDoubleValue) { +CustomAttribute::CustomAttribute(std::string initStringKey, const double initDoubleValue) : + stringKey(std::move(initStringKey)), value(initDoubleValue) { } // Constructor for boolean -CustomAttribute::CustomAttribute(const std::string &initStringKey, const bool initBoolValue) : - stringKey(initStringKey), value(initBoolValue) { +CustomAttribute::CustomAttribute(std::string initStringKey, const bool initBoolValue) : + stringKey(std::move(initStringKey)), value(initBoolValue) { } const std::string &CustomAttribute::getStringKey() const { diff --git a/src/items/functions/item/custom_attribute.hpp b/src/items/functions/item/custom_attribute.hpp index e91832c6b6b..b44e20bf477 100644 --- a/src/items/functions/item/custom_attribute.hpp +++ b/src/items/functions/item/custom_attribute.hpp @@ -16,10 +16,10 @@ class CustomAttribute { CustomAttribute(); ~CustomAttribute(); - CustomAttribute(const std::string &initStringKey, const int64_t initInt64Value); - CustomAttribute(const std::string &initStringKey, const std::string &initStringValue); - CustomAttribute(const std::string &initStringKey, const double initDoubleValue); - CustomAttribute(const std::string &initStringKey, const bool initBoolValue); + CustomAttribute(std::string initStringKey, int64_t initInt64Value); + CustomAttribute(std::string initStringKey, const std::string &initStringValue); + CustomAttribute(std::string initStringKey, double initDoubleValue); + CustomAttribute(std::string initStringKey, bool initBoolValue); const std::string &getStringKey() const; diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp index 822d2099df2..357e0c03e8b 100644 --- a/src/items/functions/item/item_parse.cpp +++ b/src/items/functions/item/item_parse.cpp @@ -8,79 +8,83 @@ */ #include "items/functions/item/item_parse.hpp" + +#include "config/configmanager.hpp" #include "items/weapons/weapons.hpp" #include "lua/creature/movement.hpp" #include "utils/pugicast.hpp" +#include "utils/tools.hpp" #include "creatures/combat/combat.hpp" +#include "lua/scripts/scripts.hpp" -void ItemParse::initParse(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { +void ItemParse::initParse(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { // Parse all item attributes - ItemParse::parseType(tmpStrValue, attributeNode, valueAttribute, itemType); - ItemParse::parseDescription(tmpStrValue, valueAttribute, itemType); - ItemParse::parseRuneSpellName(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWeight(tmpStrValue, valueAttribute, itemType); - ItemParse::parseShowCount(tmpStrValue, valueAttribute, itemType); - ItemParse::parseArmor(tmpStrValue, valueAttribute, itemType); - ItemParse::parseDefense(tmpStrValue, valueAttribute, itemType); - ItemParse::parseExtraDefense(tmpStrValue, valueAttribute, itemType); - ItemParse::parseAttack(tmpStrValue, valueAttribute, itemType); - ItemParse::parseRotateTo(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWrapContainer(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWrapableTo(tmpStrValue, valueAttribute, itemType); - ItemParse::parseMovable(tmpStrValue, valueAttribute, itemType); - ItemParse::parseBlockProjectTile(tmpStrValue, valueAttribute, itemType); - ItemParse::parsePickupable(tmpStrValue, valueAttribute, itemType); - ItemParse::parseFloorChange(tmpStrValue, valueAttribute, itemType); - ItemParse::parseContainerSize(tmpStrValue, valueAttribute, itemType); - ItemParse::parseFluidSource(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWriteables(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWeaponType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseSlotType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseAmmoType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseShootType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseMagicEffect(tmpStrValue, valueAttribute, itemType); - ItemParse::parseLootType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseRange(tmpStrValue, valueAttribute, itemType); - ItemParse::parseDecayTo(tmpStrValue, valueAttribute, itemType); - ItemParse::parseDuration(tmpStrValue, valueAttribute, itemType); - ItemParse::parseTransform(tmpStrValue, valueAttribute, itemType); - ItemParse::parseCharges(tmpStrValue, valueAttribute, itemType); - ItemParse::parseShowAttributes(tmpStrValue, valueAttribute, itemType); - ItemParse::parseHitChance(tmpStrValue, valueAttribute, itemType); - ItemParse::parseInvisible(tmpStrValue, valueAttribute, itemType); - ItemParse::parseSpeed(tmpStrValue, valueAttribute, itemType); - ItemParse::parseHealthAndMana(tmpStrValue, valueAttribute, itemType); - ItemParse::parseSkills(tmpStrValue, valueAttribute, itemType); - ItemParse::parseCriticalHit(tmpStrValue, valueAttribute, itemType); - ItemParse::parseLifeAndManaLeech(tmpStrValue, valueAttribute, itemType); - ItemParse::parseMaxHitAndManaPoints(tmpStrValue, valueAttribute, itemType); - ItemParse::parseMagicLevelPoint(tmpStrValue, valueAttribute, itemType); - ItemParse::parseFieldAbsorbPercent(tmpStrValue, valueAttribute, itemType); - ItemParse::parseAbsorbPercent(tmpStrValue, valueAttribute, itemType); - ItemParse::parseSupressDrunk(tmpStrValue, valueAttribute, itemType); - ItemParse::parseField(tmpStrValue, attributeNode, valueAttribute, itemType); - ItemParse::parseReplaceable(tmpStrValue, valueAttribute, itemType); - ItemParse::parseLevelDoor(tmpStrValue, valueAttribute, itemType); - ItemParse::parseBeds(tmpStrValue, valueAttribute, itemType); - ItemParse::parseElement(tmpStrValue, valueAttribute, itemType); - ItemParse::parseWalk(tmpStrValue, valueAttribute, itemType); - ItemParse::parseAllowDistanceRead(tmpStrValue, valueAttribute, itemType); - ItemParse::parseImbuement(tmpStrValue, attributeNode, valueAttribute, itemType); - ItemParse::parseAugment(tmpStrValue, attributeNode, valueAttribute, itemType); - ItemParse::parseStackSize(tmpStrValue, valueAttribute, itemType); - ItemParse::parseSpecializedMagicLevelPoint(tmpStrValue, valueAttribute, itemType); - ItemParse::parseMagicShieldCapacity(tmpStrValue, valueAttribute, itemType); - ItemParse::parsePerfecShot(tmpStrValue, valueAttribute, itemType); - ItemParse::parseCleavePercent(tmpStrValue, valueAttribute, itemType); - ItemParse::parseReflectDamage(tmpStrValue, valueAttribute, itemType); - ItemParse::parseTransformOnUse(tmpStrValue, valueAttribute, itemType); - ItemParse::parsePrimaryType(tmpStrValue, valueAttribute, itemType); - ItemParse::parseHouseRelated(tmpStrValue, valueAttribute, itemType); - ItemParse::parseUnscriptedItems(tmpStrValue, attributeNode, valueAttribute, itemType); + ItemParse::parseType(stringValue, attributeNode, valueAttribute, itemType); + ItemParse::parseDescription(stringValue, valueAttribute, itemType); + ItemParse::parseRuneSpellName(stringValue, valueAttribute, itemType); + ItemParse::parseWeight(stringValue, valueAttribute, itemType); + ItemParse::parseShowCount(stringValue, valueAttribute, itemType); + ItemParse::parseArmor(stringValue, valueAttribute, itemType); + ItemParse::parseDefense(stringValue, valueAttribute, itemType); + ItemParse::parseExtraDefense(stringValue, valueAttribute, itemType); + ItemParse::parseAttack(stringValue, valueAttribute, itemType); + ItemParse::parseRotateTo(stringValue, valueAttribute, itemType); + ItemParse::parseWrapContainer(stringValue, valueAttribute, itemType); + ItemParse::parseWrapableTo(stringValue, valueAttribute, itemType); + ItemParse::parseMovable(stringValue, valueAttribute, itemType); + ItemParse::parseBlockProjectTile(stringValue, valueAttribute, itemType); + ItemParse::parsePickupable(stringValue, valueAttribute, itemType); + ItemParse::parseFloorChange(stringValue, valueAttribute, itemType); + ItemParse::parseContainerSize(stringValue, valueAttribute, itemType); + ItemParse::parseFluidSource(stringValue, valueAttribute, itemType); + ItemParse::parseWriteables(stringValue, valueAttribute, itemType); + ItemParse::parseWeaponType(stringValue, valueAttribute, itemType); + ItemParse::parseSlotType(stringValue, valueAttribute, itemType); + ItemParse::parseAmmoType(stringValue, valueAttribute, itemType); + ItemParse::parseShootType(stringValue, valueAttribute, itemType); + ItemParse::parseMagicEffect(stringValue, valueAttribute, itemType); + ItemParse::parseLootType(stringValue, valueAttribute, itemType); + ItemParse::parseRange(stringValue, valueAttribute, itemType); + ItemParse::parseDecayTo(stringValue, valueAttribute, itemType); + ItemParse::parseDuration(stringValue, valueAttribute, itemType); + ItemParse::parseTransform(stringValue, valueAttribute, itemType); + ItemParse::parseCharges(stringValue, valueAttribute, itemType); + ItemParse::parseShowAttributes(stringValue, valueAttribute, itemType); + ItemParse::parseHitChance(stringValue, valueAttribute, itemType); + ItemParse::parseInvisible(stringValue, valueAttribute, itemType); + ItemParse::parseSpeed(stringValue, valueAttribute, itemType); + ItemParse::parseHealthAndMana(stringValue, valueAttribute, itemType); + ItemParse::parseSkills(stringValue, valueAttribute, itemType); + ItemParse::parseCriticalHit(stringValue, valueAttribute, itemType); + ItemParse::parseLifeAndManaLeech(stringValue, valueAttribute, itemType); + ItemParse::parseMaxHitAndManaPoints(stringValue, valueAttribute, itemType); + ItemParse::parseMagicLevelPoint(stringValue, valueAttribute, itemType); + ItemParse::parseFieldAbsorbPercent(stringValue, valueAttribute, itemType); + ItemParse::parseAbsorbPercent(stringValue, valueAttribute, itemType); + ItemParse::parseSupressDrunk(stringValue, valueAttribute, itemType); + ItemParse::parseField(stringValue, attributeNode, valueAttribute, itemType); + ItemParse::parseReplaceable(stringValue, valueAttribute, itemType); + ItemParse::parseLevelDoor(stringValue, valueAttribute, itemType); + ItemParse::parseBeds(stringValue, valueAttribute, itemType); + ItemParse::parseElement(stringValue, valueAttribute, itemType); + ItemParse::parseWalk(stringValue, valueAttribute, itemType); + ItemParse::parseAllowDistanceRead(stringValue, valueAttribute, itemType); + ItemParse::parseImbuement(stringValue, attributeNode, valueAttribute, itemType); + ItemParse::parseAugment(stringValue, attributeNode, valueAttribute, itemType); + ItemParse::parseStackSize(stringValue, valueAttribute, itemType); + ItemParse::parseSpecializedMagicLevelPoint(stringValue, valueAttribute, itemType); + ItemParse::parseMagicShieldCapacity(stringValue, valueAttribute, itemType); + ItemParse::parsePerfecShot(stringValue, valueAttribute, itemType); + ItemParse::parseCleavePercent(stringValue, valueAttribute, itemType); + ItemParse::parseReflectDamage(stringValue, valueAttribute, itemType); + ItemParse::parseTransformOnUse(stringValue, valueAttribute, itemType); + ItemParse::parsePrimaryType(stringValue, valueAttribute, itemType); + ItemParse::parseHouseRelated(stringValue, valueAttribute, itemType); + ItemParse::parseUnscriptedItems(stringValue, attributeNode, valueAttribute, itemType); } void ItemParse::parseDummyRate(pugi::xml_node attributeNode, ItemType &itemType) { - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; @@ -93,17 +97,16 @@ void ItemParse::parseDummyRate(pugi::xml_node attributeNode, ItemType &itemType) auto stringValue = asLowerCaseString(subKeyAttribute.as_string()); if (stringValue == "rate") { - uint16_t rate = subValueAttribute.as_uint(); + const uint16_t rate = subValueAttribute.as_uint(); Item::items.addDummyId(itemType.id, rate); } } } -void ItemParse::parseType(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseType(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "type") { - stringValue = asLowerCaseString(valueAttribute.as_string()); - auto itemMap = ItemTypesMap.find(stringValue); + auto stringValue = asLowerCaseString(valueAttribute.as_string()); + const auto &itemMap = ItemTypesMap.find(stringValue); if (itemMap != ItemTypesMap.end()) { itemType.type = itemMap->second; if (itemType.type == ITEM_TYPE_CONTAINER) { @@ -121,8 +124,7 @@ void ItemParse::parseType(const std::string &tmpStrValue, pugi::xml_node attribu } } -void ItemParse::parseDescription(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseDescription(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "description") { itemType.description = valueAttribute.as_string(); if (g_configManager().getBoolean(TOGGLE_GOLD_POUCH_QUICKLOOT_ONLY) && itemType.id == ITEM_GOLD_POUCH) { @@ -133,103 +135,89 @@ void ItemParse::parseDescription(const std::string &tmpStrValue, pugi::xml_attri } } -void ItemParse::parseRuneSpellName(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseRuneSpellName(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "runespellname") { itemType.runeSpellName = valueAttribute.as_string(); } } -void ItemParse::parseWeight(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWeight(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "weight") { itemType.weight = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseShowCount(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseShowCount(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "showcount") { itemType.showCount = valueAttribute.as_bool(); } } -void ItemParse::parseArmor(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseArmor(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "armor") { itemType.armor = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseDefense(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseDefense(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "defense") { itemType.defense = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseExtraDefense(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseExtraDefense(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "extradef") { itemType.extraDefense = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseAttack(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseAttack(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "attack") { itemType.attack = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseRotateTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseRotateTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "rotateto") { itemType.rotateTo = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseWrapContainer(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWrapContainer(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "wrapcontainer") { itemType.wrapContainer = valueAttribute.as_bool(); } } -void ItemParse::parseWrapableTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWrapableTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "wrapableto") { itemType.wrapableTo = pugi::cast<int32_t>(valueAttribute.value()); itemType.wrapable = true; } } -void ItemParse::parseMovable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseMovable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "movable") { itemType.movable = valueAttribute.as_bool(); } } -void ItemParse::parseBlockProjectTile(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseBlockProjectTile(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "blockprojectile") { itemType.blockProjectile = valueAttribute.as_bool(); } } -void ItemParse::parsePickupable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parsePickupable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "allowpickupable" || stringValue == "pickupable") { itemType.pickupable = valueAttribute.as_bool(); } } -void ItemParse::parseFloorChange(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseFloorChange(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "floorchange") { - stringValue = asLowerCaseString(valueAttribute.as_string()); - auto itemMap = TileStatesMap.find(stringValue); + auto lowerString = asLowerCaseString(valueAttribute.as_string()); + const auto &itemMap = TileStatesMap.find(lowerString); if (itemMap != TileStatesMap.end()) { itemType.floorChange = itemMap->second; } else { @@ -238,18 +226,16 @@ void ItemParse::parseFloorChange(const std::string &tmpStrValue, pugi::xml_attri } } -void ItemParse::parseContainerSize(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseContainerSize(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "containersize") { itemType.maxItems = pugi::cast<uint16_t>(valueAttribute.value()); } } -void ItemParse::parseFluidSource(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseFluidSource(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "fluidsource") { - stringValue = asLowerCaseString(valueAttribute.as_string()); - auto itemMap = FluidTypesMap.find(stringValue); + auto lowerString = asLowerCaseString(valueAttribute.as_string()); + const auto &itemMap = FluidTypesMap.find(lowerString); if (itemMap != FluidTypesMap.end()) { itemType.fluidSource = itemMap->second; } else { @@ -258,8 +244,7 @@ void ItemParse::parseFluidSource(const std::string &tmpStrValue, pugi::xml_attri } } -void ItemParse::parseWriteables(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWriteables(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "readable") { itemType.canReadText = valueAttribute.as_bool(); } else if (stringValue == "writeable") { @@ -272,13 +257,12 @@ void ItemParse::parseWriteables(const std::string &tmpStrValue, pugi::xml_attrib } } -void ItemParse::parseWeaponType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWeaponType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "weapontype") { - stringValue = asLowerCaseString(valueAttribute.as_string()); - auto itemMap = WeaponTypesMap.find(stringValue); + auto lowerString = asLowerCaseString(valueAttribute.as_string()); + const auto &itemMap = WeaponTypesMap.find(lowerString); if (itemMap != WeaponTypesMap.end()) { - if (tmpStrValue == "spellbook") { + if (stringValue == "spellbook") { itemType.spellbook = true; } itemType.weaponType = itemMap->second; @@ -288,34 +272,33 @@ void ItemParse::parseWeaponType(const std::string &tmpStrValue, pugi::xml_attrib } } -void ItemParse::parseSlotType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseSlotType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "slottype") { itemType.slotPosition = SLOTP_HAND; - stringValue = asLowerCaseString(valueAttribute.as_string()); - if (stringValue == "head") { + auto subStringValue = asLowerCaseString(valueAttribute.as_string()); + if (subStringValue == "head") { itemType.slotPosition |= SLOTP_HEAD; - } else if (stringValue == "body") { + } else if (subStringValue == "body") { itemType.slotPosition |= SLOTP_ARMOR; - } else if (stringValue == "legs") { + } else if (subStringValue == "legs") { itemType.slotPosition |= SLOTP_LEGS; - } else if (stringValue == "feet") { + } else if (subStringValue == "feet") { itemType.slotPosition |= SLOTP_FEET; - } else if (stringValue == "backpack") { + } else if (subStringValue == "backpack") { itemType.slotPosition |= SLOTP_BACKPACK; - } else if (stringValue == "two-handed") { + } else if (subStringValue == "two-handed") { itemType.slotPosition |= SLOTP_TWO_HAND; - } else if (stringValue == "right-hand") { + } else if (subStringValue == "right-hand") { itemType.slotPosition &= ~SLOTP_LEFT; - } else if (stringValue == "left-hand") { + } else if (subStringValue == "left-hand") { itemType.slotPosition &= ~SLOTP_RIGHT; - } else if (stringValue == "necklace") { + } else if (subStringValue == "necklace") { itemType.slotPosition |= SLOTP_NECKLACE; - } else if (stringValue == "ring") { + } else if (subStringValue == "ring") { itemType.slotPosition |= SLOTP_RING; - } else if (stringValue == "ammo") { + } else if (subStringValue == "ammo") { itemType.slotPosition |= SLOTP_AMMO; - } else if (stringValue == "hand") { + } else if (subStringValue == "hand") { itemType.slotPosition |= SLOTP_HAND; } else { g_logger().warn("[itemParseSlotType - Items::parseItemNode] - Unknown slotType {}", valueAttribute.as_string()); @@ -323,8 +306,7 @@ void ItemParse::parseSlotType(const std::string &tmpStrValue, pugi::xml_attribut } } -void ItemParse::parseAmmoType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseAmmoType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "ammotype") { itemType.ammoType = getAmmoType(asLowerCaseString(valueAttribute.as_string())); if (itemType.ammoType == AMMO_NONE) { @@ -333,10 +315,9 @@ void ItemParse::parseAmmoType(const std::string &tmpStrValue, pugi::xml_attribut } } -void ItemParse::parseShootType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseShootType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "shoottype") { - ShootType_t shoot = getShootType(asLowerCaseString(valueAttribute.as_string())); + const ShootType_t &shoot = getShootType(asLowerCaseString(valueAttribute.as_string())); if (shoot != CONST_ANI_NONE) { itemType.shootType = shoot; } else { @@ -345,10 +326,9 @@ void ItemParse::parseShootType(const std::string &tmpStrValue, pugi::xml_attribu } } -void ItemParse::parseMagicEffect(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseMagicEffect(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "effect") { - MagicEffectClasses effect = getMagicEffect(asLowerCaseString(valueAttribute.as_string())); + const MagicEffectClasses &effect = getMagicEffect(asLowerCaseString(valueAttribute.as_string())); if (effect != CONST_ME_NONE) { itemType.magicEffect = effect; } else { @@ -357,29 +337,25 @@ void ItemParse::parseMagicEffect(const std::string &tmpStrValue, pugi::xml_attri } } -void ItemParse::parseLootType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseLootType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "loottype") { itemType.type = Item::items.getLootType(valueAttribute.as_string()); } } -void ItemParse::parseRange(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseRange(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "range") { itemType.shootRange = pugi::cast<uint8_t>(valueAttribute.value()); } } -void ItemParse::parseDecayTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseDecayTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "decayto") { itemType.decayTo = pugi::cast<uint16_t>(valueAttribute.value()); } } -void ItemParse::parseDuration(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseDuration(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "duration") { itemType.decayTime = pugi::cast<uint32_t>(valueAttribute.value()); } else if (stringValue == "stopduration") { @@ -389,8 +365,7 @@ void ItemParse::parseDuration(const std::string &tmpStrValue, pugi::xml_attribut } } -void ItemParse::parseTransform(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseTransform(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "transformequipto") { itemType.transformEquipTo = pugi::cast<uint16_t>(valueAttribute.value()); if (itemType.transformEquipTo == itemType.decayTo) { @@ -415,8 +390,7 @@ void ItemParse::parseTransform(const std::string &tmpStrValue, pugi::xml_attribu } } -void ItemParse::parseCharges(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseCharges(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "charges") { itemType.charges = pugi::cast<uint32_t>(valueAttribute.value()); } else if (stringValue == "showcharges") { @@ -424,15 +398,13 @@ void ItemParse::parseCharges(const std::string &tmpStrValue, pugi::xml_attribute } } -void ItemParse::parseShowAttributes(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string lowerStringValue = asLowerCaseString(tmpStrValue); - if (lowerStringValue == "showattributes") { +void ItemParse::parseShowAttributes(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "showattributes") { itemType.showAttributes = valueAttribute.as_bool(); } } -void ItemParse::parseHitChance(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseHitChance(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "hitchance") { itemType.hitChance = std::min<int8_t>(100, std::max<int8_t>(-100, pugi::cast<int8_t>(valueAttribute.value()))); } else if (stringValue == "maxhitchance") { @@ -440,22 +412,19 @@ void ItemParse::parseHitChance(const std::string &tmpStrValue, pugi::xml_attribu } } -void ItemParse::parseInvisible(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseInvisible(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "invisible") { itemType.getAbilities().invisible = valueAttribute.as_bool(); } } -void ItemParse::parseSpeed(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseSpeed(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "speed") { itemType.getAbilities().speed = pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseHealthAndMana(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseHealthAndMana(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "healthgain") { Abilities &abilities = itemType.getAbilities(); abilities.regeneration = true; @@ -477,8 +446,7 @@ void ItemParse::parseHealthAndMana(const std::string &tmpStrValue, pugi::xml_att } } -void ItemParse::parseSkills(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseSkills(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "skillsword") { itemType.getAbilities().skills[SKILL_SWORD] = pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "skillaxe") { @@ -496,8 +464,7 @@ void ItemParse::parseSkills(const std::string &tmpStrValue, pugi::xml_attribute } } -void ItemParse::parseCriticalHit(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseCriticalHit(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "criticalhitchance") { itemType.getAbilities().skills[SKILL_CRITICAL_HIT_CHANCE] = pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "criticalhitdamage") { @@ -505,8 +472,7 @@ void ItemParse::parseCriticalHit(const std::string &tmpStrValue, pugi::xml_attri } } -void ItemParse::parseLifeAndManaLeech(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseLifeAndManaLeech(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "lifeleechchance") { itemType.getAbilities().skills[SKILL_LIFE_LEECH_CHANCE] = pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "lifeleechamount") { @@ -518,8 +484,7 @@ void ItemParse::parseLifeAndManaLeech(const std::string &tmpStrValue, pugi::xml_ } } -void ItemParse::parseMaxHitAndManaPoints(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseMaxHitAndManaPoints(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "maxhitpoints") { itemType.getAbilities().stats[STAT_MAXHITPOINTS] = pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "maxhitpointspercent") { @@ -531,8 +496,7 @@ void ItemParse::parseMaxHitAndManaPoints(const std::string &tmpStrValue, pugi::x } } -void ItemParse::parseMagicLevelPoint(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseMagicLevelPoint(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "magiclevelpoints" || stringValue == "magicpoints") { itemType.getAbilities().stats[STAT_MAGICPOINTS] = pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "magiclevelpointspercent") { @@ -540,8 +504,7 @@ void ItemParse::parseMagicLevelPoint(const std::string &tmpStrValue, pugi::xml_a } } -void ItemParse::parseFieldAbsorbPercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseFieldAbsorbPercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "fieldabsorbpercentenergy") { itemType.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast<int16_t>(valueAttribute.value()); } else if (stringValue == "fieldabsorbpercentfire") { @@ -551,23 +514,22 @@ void ItemParse::parseFieldAbsorbPercent(const std::string &tmpStrValue, pugi::xm } } -void ItemParse::parseAbsorbPercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseAbsorbPercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "absorbpercentall") { - int16_t value = pugi::cast<int16_t>(valueAttribute.value()); + const auto value = pugi::cast<int16_t>(valueAttribute.value()); Abilities &abilities = itemType.getAbilities(); for (auto &i : abilities.absorbPercent) { i += value; } } else if (stringValue == "absorbpercentelements") { - int16_t value = pugi::cast<int16_t>(valueAttribute.value()); + const auto value = pugi::cast<int16_t>(valueAttribute.value()); Abilities &abilities = itemType.getAbilities(); abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; } else if (stringValue == "absorbpercentmagic") { - int16_t value = pugi::cast<int16_t>(valueAttribute.value()); + const auto value = pugi::cast<int16_t>(valueAttribute.value()); Abilities &abilities = itemType.getAbilities(); abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; @@ -600,8 +562,7 @@ void ItemParse::parseAbsorbPercent(const std::string &tmpStrValue, pugi::xml_att } } -void ItemParse::parseSupressDrunk(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseSupressDrunk(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (valueAttribute.as_bool()) { ConditionType_t conditionType = CONDITION_NONE; if (stringValue == "suppressdrunk") { @@ -628,8 +589,8 @@ void ItemParse::parseSupressDrunk(const std::string &tmpStrValue, pugi::xml_attr } } -std::tuple<ConditionId_t, ConditionType_t> ItemParse::parseFieldConditions(std::string lowerStringValue, pugi::xml_attribute valueAttribute) { - lowerStringValue = asLowerCaseString(valueAttribute.as_string()); +std::tuple<ConditionId_t, ConditionType_t> ItemParse::parseFieldConditions(pugi::xml_attribute valueAttribute) { + auto lowerStringValue = asLowerCaseString(valueAttribute.as_string()); ConditionId_t conditionId = CONDITIONID_COMBAT; ConditionType_t conditionType = CONDITION_NONE; if (lowerStringValue == "fire") { @@ -653,8 +614,8 @@ std::tuple<ConditionId_t, ConditionType_t> ItemParse::parseFieldConditions(std:: return std::make_tuple(CONDITIONID_DEFAULT, CONDITION_NONE); } -CombatType_t ItemParse::parseFieldCombatType(std::string lowerStringValue, pugi::xml_attribute valueAttribute) { - lowerStringValue = asLowerCaseString(valueAttribute.as_string()); +CombatType_t ItemParse::parseFieldCombatType(pugi::xml_attribute valueAttribute) { + auto lowerStringValue = asLowerCaseString(valueAttribute.as_string()); if (lowerStringValue == "fire") { return COMBAT_FIREDAMAGE; } else if (lowerStringValue == "energy") { @@ -671,13 +632,13 @@ CombatType_t ItemParse::parseFieldCombatType(std::string lowerStringValue, pugi: return COMBAT_NONE; } -void ItemParse::parseFieldCombatDamage(std::shared_ptr<ConditionDamage> conditionDamage, std::string stringValue, pugi::xml_node attributeNode) { +void ItemParse::parseFieldCombatDamage(const std::shared_ptr<ConditionDamage> &conditionDamage, pugi::xml_node attributeNode) { uint32_t combatTicks = 0; int32_t combatDamage = 0; int32_t combatStart = 0; int32_t combatCount = 1; - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; @@ -688,7 +649,7 @@ void ItemParse::parseFieldCombatDamage(std::shared_ptr<ConditionDamage> conditio continue; } - stringValue = asLowerCaseString(subKeyAttribute.as_string()); + auto stringValue = asLowerCaseString(subKeyAttribute.as_string()); if (stringValue == "ticks") { combatTicks = pugi::cast<uint32_t>(subValueAttribute.value()); } else if (stringValue == "count") { @@ -703,7 +664,7 @@ void ItemParse::parseFieldCombatDamage(std::shared_ptr<ConditionDamage> conditio std::list<int32_t> damageList; ConditionDamage::generateDamageList(combatDamage, combatStart, damageList); - for (int32_t damageValue : damageList) { + for (const int32_t damageValue : damageList) { conditionDamage->addDamage(1, combatTicks, -damageValue); } @@ -712,25 +673,19 @@ void ItemParse::parseFieldCombatDamage(std::shared_ptr<ConditionDamage> conditio } } -void ItemParse::parseField(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue == "field") { +void ItemParse::parseField(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "field") { CombatType_t combatType = COMBAT_NONE; - std::shared_ptr<ConditionDamage> conditionDamage = nullptr; - // Parse fields conditions (fire/energy/poison/drown/physical) - combatType = parseFieldCombatType(tmpStrValue, valueAttribute); - auto [conditionId, conditionType] = parseFieldConditions(tmpStrValue, valueAttribute); - + combatType = parseFieldCombatType(valueAttribute); + auto [conditionId, conditionType] = parseFieldConditions(valueAttribute); if (combatType != COMBAT_NONE) { - if (conditionDamage) { - } - - conditionDamage = std::make_shared<ConditionDamage>(conditionId, conditionType); + auto conditionDamage = std::make_shared<ConditionDamage>(conditionId, conditionType); itemType.combatType = combatType; itemType.conditionDamage = conditionDamage; - parseFieldCombatDamage(conditionDamage, tmpStrValue, attributeNode); + parseFieldCombatDamage(conditionDamage, attributeNode); conditionDamage->setParam(CONDITION_PARAM_FIELD, 1); @@ -741,28 +696,25 @@ void ItemParse::parseField(const std::string &tmpStrValue, pugi::xml_node attrib } } -void ItemParse::parseReplaceable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseReplaceable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "replaceable") { itemType.replaceable = valueAttribute.as_bool(); } } -void ItemParse::parseLevelDoor(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseLevelDoor(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "leveldoor") { itemType.levelDoor = pugi::cast<uint32_t>(valueAttribute.value()); } } -void ItemParse::parseBeds(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseBeds(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "partnerdirection") { itemType.bedPartnerDir = getDirection(valueAttribute.as_string()); } if (stringValue == "maletransformto") { - uint16_t valueMale = pugi::cast<uint16_t>(valueAttribute.value()); + const auto valueMale = pugi::cast<uint16_t>(valueAttribute.value()); ItemType &other = Item::items.getItemType(valueMale); itemType.transformToOnUse[PLAYERSEX_MALE] = valueMale; if (other.transformToFree == 0) { @@ -773,7 +725,7 @@ void ItemParse::parseBeds(const std::string &tmpStrValue, pugi::xml_attribute va itemType.transformToOnUse[PLAYERSEX_FEMALE] = valueMale; } } else if (stringValue == "femaletransformto") { - uint16_t valueFemale = pugi::cast<uint16_t>(valueAttribute.value()); + const auto valueFemale = pugi::cast<uint16_t>(valueAttribute.value()); ItemType &other = Item::items.getItemType(valueFemale); itemType.transformToOnUse[PLAYERSEX_FEMALE] = valueFemale; @@ -794,8 +746,7 @@ void ItemParse::parseBeds(const std::string &tmpStrValue, pugi::xml_attribute va } } -void ItemParse::parseElement(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseElement(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "elementice") { Abilities &abilities = itemType.getAbilities(); abilities.elementDamage = pugi::cast<uint16_t>(valueAttribute.value()); @@ -823,8 +774,7 @@ void ItemParse::parseElement(const std::string &tmpStrValue, pugi::xml_attribute } } -void ItemParse::parseWalk(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseWalk(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "walkstack") { itemType.walkStack = valueAttribute.as_bool(); } else if (stringValue == "blocking") { @@ -832,20 +782,19 @@ void ItemParse::parseWalk(const std::string &tmpStrValue, pugi::xml_attribute va } } -void ItemParse::parseAllowDistanceRead(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseAllowDistanceRead(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "allowdistread") { itemType.allowDistRead = booleanString(valueAttribute.as_string()); } } -void ItemParse::parseImbuement(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue != "imbuementslot") { +void ItemParse::parseImbuement(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue != "imbuementslot") { return; } itemType.imbuementSlot = pugi::cast<uint8_t>(valueAttribute.value()); - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; @@ -856,9 +805,9 @@ void ItemParse::parseImbuement(const std::string &tmpStrValue, pugi::xml_node at continue; } - auto itemMap = ImbuementsTypeMap.find(asLowerCaseString(subKeyAttribute.as_string())); + const auto &itemMap = ImbuementsTypeMap.find(asLowerCaseString(subKeyAttribute.as_string())); if (itemMap != ImbuementsTypeMap.end()) { - ImbuementTypes_t imbuementType = getImbuementType(asLowerCaseString(subKeyAttribute.as_string())); + const ImbuementTypes_t imbuementType = getImbuementType(asLowerCaseString(subKeyAttribute.as_string())); if (imbuementType != IMBUEMENT_NONE) { itemType.setImbuementType(imbuementType, pugi::cast<uint16_t>(subValueAttribute.value())); continue; @@ -869,8 +818,8 @@ void ItemParse::parseImbuement(const std::string &tmpStrValue, pugi::xml_node at } } -void ItemParse::parseAugment(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue != "augments") { +void ItemParse::parseAugment(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue != "augments") { return; } @@ -921,8 +870,7 @@ void ItemParse::parseAugment(const std::string &tmpStrValue, pugi::xml_node attr } } -void ItemParse::parseStackSize(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseStackSize(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { if (stringValue == "stacksize") { auto stackSize = pugi::cast<uint16_t>(valueAttribute.value()); if (stackSize > 255) { @@ -933,8 +881,7 @@ void ItemParse::parseStackSize(const std::string &tmpStrValue, pugi::xml_attribu } } -void ItemParse::parseSpecializedMagicLevelPoint(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseSpecializedMagicLevelPoint(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { Abilities &abilities = itemType.getAbilities(); if (stringValue == "deathmagiclevelpoints") { abilities.specializedMagicLevel[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast<int32_t>(valueAttribute.value()); @@ -963,8 +910,7 @@ void ItemParse::parseSpecializedMagicLevelPoint(const std::string &tmpStrValue, } } -void ItemParse::parseMagicShieldCapacity(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseMagicShieldCapacity(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { Abilities &abilities = itemType.getAbilities(); if (stringValue == "magicshieldcapacitypercent") { abilities.magicShieldCapacityPercent += pugi::cast<int32_t>(valueAttribute.value()); @@ -973,8 +919,7 @@ void ItemParse::parseMagicShieldCapacity(const std::string &tmpStrValue, pugi::x } } -void ItemParse::parsePerfecShot(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parsePerfecShot(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { Abilities &abilities = itemType.getAbilities(); if (stringValue == "perfectshotdamage") { abilities.perfectShotDamage = pugi::cast<int32_t>(valueAttribute.value()); @@ -983,41 +928,39 @@ void ItemParse::parsePerfecShot(const std::string &tmpStrValue, pugi::xml_attrib } } -void ItemParse::parseCleavePercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseCleavePercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { Abilities &abilities = itemType.getAbilities(); if (stringValue == "cleavepercent") { abilities.cleavePercent += pugi::cast<int32_t>(valueAttribute.value()); } } -void ItemParse::parseReflectDamage(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - std::string stringValue = tmpStrValue; +void ItemParse::parseReflectDamage(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { Abilities &abilities = itemType.getAbilities(); if (stringValue == "reflectdamage") { abilities.reflectFlat[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast<int32_t>(valueAttribute.value()); } else if (stringValue == "reflectpercentall") { - int32_t value = pugi::cast<int32_t>(valueAttribute.value()); - std::transform(std::begin(abilities.reflectPercent), std::end(abilities.reflectPercent), std::begin(abilities.reflectPercent), [&](const auto &i) { + auto value = pugi::cast<int32_t>(valueAttribute.value()); + std::ranges::transform(abilities.reflectPercent, std::begin(abilities.reflectPercent), [&](const auto &i) { return i + value; }); } } -void ItemParse::parseTransformOnUse(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue == "transformonuse") { +void ItemParse::parseTransformOnUse(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "transformonuse") { itemType.m_transformOnUse = pugi::cast<uint16_t>(valueAttribute.value()); } } -void ItemParse::parsePrimaryType(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue == "primarytype") { +void ItemParse::parsePrimaryType(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "primarytype") { itemType.m_primaryType = asLowerCaseString(valueAttribute.as_string()); } } -void ItemParse::parseHouseRelated(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue == "usedbyhouseguests") { +void ItemParse::parseHouseRelated(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "usedbyhouseguests") { g_logger().debug("[{}] item {}, used by guests {}", __FUNCTION__, itemType.id, valueAttribute.as_bool()); itemType.m_canBeUsedByGuests = valueAttribute.as_bool(); } @@ -1026,10 +969,9 @@ void ItemParse::parseHouseRelated(std::string_view tmpStrValue, pugi::xml_attrib void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attributeNode, MoveEvent_t eventType /*= MOVE_EVENT_NONE*/, WeaponType_t weaponType /*= WEAPON_NONE*/) { std::shared_ptr<MoveEvent> moveevent; if (eventType != MOVE_EVENT_NONE) { - moveevent = std::make_shared<MoveEvent>(&g_moveEvents().getScriptInterface()); + moveevent = std::make_shared<MoveEvent>(); moveevent->setItemId(itemType.id); moveevent->setEventType(eventType); - moveevent->setFromXML(true); if (eventType == MOVE_EVENT_EQUIP) { moveevent->equipFunction = moveevent->EquipItem; @@ -1049,11 +991,11 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri std::shared_ptr<Weapon> weapon = nullptr; if (weaponType != WEAPON_NONE) { if (weaponType == WEAPON_DISTANCE || weaponType == WEAPON_AMMO || weaponType == WEAPON_MISSILE) { - weapon = std::make_shared<WeaponDistance>(&g_weapons().getScriptInterface()); + weapon = std::make_shared<WeaponDistance>(); } else if (weaponType == WEAPON_WAND) { - weapon = std::make_shared<WeaponWand>(&g_weapons().getScriptInterface()); + weapon = std::make_shared<WeaponWand>(); } else { - weapon = std::make_shared<WeaponMelee>(&g_weapons().getScriptInterface()); + weapon = std::make_shared<WeaponMelee>(); } weapon->weaponType = weaponType; @@ -1063,7 +1005,7 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri } uint32_t fromDamage = 0; uint32_t toDamage = 0; - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; @@ -1132,7 +1074,7 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri std::string token; while (std::getline(ss, token, ',')) { - token.erase(token.begin(), std::find_if(token.begin(), token.end(), [](unsigned char ch) { + token.erase(token.begin(), std::ranges::find_if(token, [](unsigned char ch) { return !std::isspace(ch); })); token.erase(std::find_if(token.rbegin(), token.rend(), [](unsigned char ch) { @@ -1231,14 +1173,14 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri } if (weapon) { - if (auto weaponWand = dynamic_pointer_cast<WeaponWand>(weapon)) { + if (const auto &weaponWand = dynamic_pointer_cast<WeaponWand>(weapon)) { g_logger().trace("Added weapon damage from '{}', to '{}'", fromDamage, toDamage); weaponWand->setMinChange(fromDamage); weaponWand->setMaxChange(toDamage); weaponWand->configureWeapon(itemType); } - auto combat = weapon->getCombat(); + const auto &combat = weapon->getCombat(); if (combat) { combat->setupChain(weapon); } @@ -1260,15 +1202,15 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri } } -void ItemParse::parseUnscriptedItems(std::string_view tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { - if (tmpStrValue == "script") { - std::string scriptName = valueAttribute.as_string(); - auto tokens = split(scriptName.data(), ';'); +void ItemParse::parseUnscriptedItems(std::string_view stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType) { + if (stringValue == "script") { + const std::string scriptName = valueAttribute.as_string(); + const auto tokens = split(scriptName, ';'); for (const auto &token : tokens) { if (token == "moveevent") { g_logger().trace("Registering moveevent for item id '{}', name '{}'", itemType.id, itemType.name); MoveEvent_t eventType = MOVE_EVENT_NONE; - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; @@ -1296,9 +1238,9 @@ void ItemParse::parseUnscriptedItems(std::string_view tmpStrValue, pugi::xml_nod createAndRegisterScript(itemType, attributeNode, eventType); } } else if (token == "weapon") { - WeaponType_t weaponType; + WeaponType_t weaponType = {}; g_logger().trace("Registering weapon for item id '{}', name '{}'", itemType.id, itemType.name); - for (auto subAttributeNode : attributeNode.children()) { + for (const auto &subAttributeNode : attributeNode.children()) { pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); if (!subKeyAttribute) { continue; diff --git a/src/items/functions/item/item_parse.hpp b/src/items/functions/item/item_parse.hpp index fb891e58ed6..6fe6fbcccd3 100644 --- a/src/items/functions/item/item_parse.hpp +++ b/src/items/functions/item/item_parse.hpp @@ -258,77 +258,77 @@ const phmap::flat_hash_map<Augment_t, ConfigKey_t> AugmentWithoutValueDescriptio class ItemParse : public Items { public: - static void initParse(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void initParse(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); private: static void parseDummyRate(pugi::xml_node attributeNode, ItemType &itemType); - static void parseType(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseDescription(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseRuneSpellName(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWeight(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseShowCount(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseArmor(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseDefense(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseExtraDefense(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseAttack(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseRotateTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWrapContainer(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWrapableTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseMovable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseBlockProjectTile(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parsePickupable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseFloorChange(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseContainerSize(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseFluidSource(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWriteables(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWeaponType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseSlotType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseAmmoType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseShootType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseMagicEffect(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseLootType(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseRange(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseDecayTo(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseDuration(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseTransform(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseCharges(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseShowAttributes(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseHitChance(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseInvisible(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseSpeed(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseHealthAndMana(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseSkills(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseCriticalHit(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseLifeAndManaLeech(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseMaxHitAndManaPoints(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseMagicLevelPoint(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseFieldAbsorbPercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseAbsorbPercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseSupressDrunk(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseField(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseReplaceable(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseLevelDoor(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseBeds(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseElement(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseWalk(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseAllowDistanceRead(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseImbuement(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseAugment(const std::string &tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseStackSize(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseSpecializedMagicLevelPoint(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseMagicShieldCapacity(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parsePerfecShot(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseCleavePercent(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseReflectDamage(const std::string &tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseTransformOnUse(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parsePrimaryType(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseHouseRelated(std::string_view tmpStrValue, pugi::xml_attribute valueAttribute, ItemType &itemType); - static void parseUnscriptedItems(std::string_view tmpStrValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseType(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseDescription(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseRuneSpellName(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWeight(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseShowCount(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseArmor(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseDefense(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseExtraDefense(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseAttack(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseRotateTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWrapContainer(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWrapableTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseMovable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseBlockProjectTile(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parsePickupable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseFloorChange(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseContainerSize(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseFluidSource(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWriteables(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWeaponType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseSlotType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseAmmoType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseShootType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseMagicEffect(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseLootType(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseRange(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseDecayTo(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseDuration(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseTransform(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseCharges(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseShowAttributes(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseHitChance(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseInvisible(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseSpeed(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseHealthAndMana(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseSkills(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseCriticalHit(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseLifeAndManaLeech(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseMaxHitAndManaPoints(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseMagicLevelPoint(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseFieldAbsorbPercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseAbsorbPercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseSupressDrunk(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseField(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseReplaceable(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseLevelDoor(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseBeds(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseElement(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseWalk(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseAllowDistanceRead(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseImbuement(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseAugment(const std::string &stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseStackSize(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseSpecializedMagicLevelPoint(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseMagicShieldCapacity(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parsePerfecShot(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseCleavePercent(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseReflectDamage(const std::string &stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseTransformOnUse(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parsePrimaryType(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseHouseRelated(std::string_view stringValue, pugi::xml_attribute valueAttribute, ItemType &itemType); + static void parseUnscriptedItems(std::string_view stringValue, pugi::xml_node attributeNode, pugi::xml_attribute valueAttribute, ItemType &itemType); private: // Parent of the function: static void parseField - static std::tuple<ConditionId_t, ConditionType_t> parseFieldConditions(std::string lowerStringValue, pugi::xml_attribute valueAttribute); - static CombatType_t parseFieldCombatType(std::string string, pugi::xml_attribute valueAttribute); - static void parseFieldCombatDamage(std::shared_ptr<ConditionDamage> conditionDamage, std::string stringValue, pugi::xml_node attributeNode); + static std::tuple<ConditionId_t, ConditionType_t> parseFieldConditions(pugi::xml_attribute valueAttribute); + static CombatType_t parseFieldCombatType(pugi::xml_attribute valueAttribute); + static void parseFieldCombatDamage(const std::shared_ptr<ConditionDamage> &conditionDamage, pugi::xml_node attributeNode); static void createAndRegisterScript(ItemType &itemType, pugi::xml_node attributeNode, MoveEvent_t eventType = MOVE_EVENT_NONE, WeaponType_t weaponType = WEAPON_NONE); }; diff --git a/src/items/item.cpp b/src/items/item.cpp index 43c172b8e7d..14af2cfb47f 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -8,18 +8,25 @@ */ #include "items/item.hpp" + +#include "config/configmanager.hpp" +#include "containers/rewards/rewardchest.hpp" +#include "creatures/combat/combat.hpp" +#include "creatures/combat/spells.hpp" +#include "creatures/players/imbuements/imbuements.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/vocations/vocation.hpp" +#include "enums/object_category.hpp" +#include "game/game.hpp" +#include "game/movement/teleport.hpp" +#include "items/bed.hpp" #include "items/containers/container.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "items/containers/mailbox/mailbox.hpp" #include "items/decay/decay.hpp" -#include "game/movement/teleport.hpp" #include "items/trashholder.hpp" -#include "items/containers/mailbox/mailbox.hpp" -#include "map/house/house.hpp" -#include "game/game.hpp" -#include "items/bed.hpp" -#include "containers/rewards/rewardchest.hpp" -#include "creatures/players/imbuements/imbuements.hpp" #include "lua/creature/actions.hpp" -#include "creatures/combat/spells.hpp" +#include "map/house/house.hpp" #define ITEM_IMBUEMENT_SLOT 500 @@ -67,7 +74,7 @@ std::shared_ptr<Item> Item::CreateItem(const uint16_t type, uint16_t count /*= 0 } else if (it.isBed()) { newItem = std::make_shared<BedItem>(type); } else { - auto itemMap = ItemTransformationMap.find(static_cast<ItemID_t>(it.id)); + const auto itemMap = ItemTransformationMap.find(static_cast<ItemID_t>(it.id)); if (itemMap != ItemTransformationMap.end()) { newItem = std::make_shared<Item>(itemMap->second, count); } else { @@ -75,7 +82,7 @@ std::shared_ptr<Item> Item::CreateItem(const uint16_t type, uint16_t count /*= 0 } } } else if (type > 0 && itemPosition) { - auto position = *itemPosition; + const auto position = *itemPosition; g_logger().warn("[Item::CreateItem] Item with id '{}', in position '{}' not exists in the appearances.dat and cannot be created.", type, position.toString()); } else { g_logger().warn("[Item::CreateItem] Item with id '{}' is not registered and cannot be created.", type); @@ -86,19 +93,19 @@ std::shared_ptr<Item> Item::CreateItem(const uint16_t type, uint16_t count /*= 0 bool Item::getImbuementInfo(uint8_t slot, ImbuementInfo* imbuementInfo) const { const CustomAttribute* attribute = getCustomAttribute(std::to_string(ITEM_IMBUEMENT_SLOT + slot)); - auto info = attribute ? attribute->getAttribute<uint32_t>() : 0; + const auto info = attribute ? attribute->getAttribute<uint32_t>() : 0; imbuementInfo->imbuement = g_imbuements().getImbuement(info & 0xFF); imbuementInfo->duration = info >> 8; return imbuementInfo->duration && imbuementInfo->imbuement; } void Item::setImbuement(uint8_t slot, uint16_t imbuementId, uint32_t duration) { - auto valueDuration = (static_cast<int64_t>(duration > 0 ? (duration << 8) | imbuementId : 0)); + const auto valueDuration = (static_cast<int64_t>(duration > 0 ? (duration << 8) | imbuementId : 0)); setCustomAttribute(std::to_string(ITEM_IMBUEMENT_SLOT + slot), valueDuration); } void Item::addImbuement(uint8_t slot, uint16_t imbuementId, uint32_t duration) { - std::shared_ptr<Player> player = getHoldingPlayer(); + const auto &player = getHoldingPlayer(); if (!player) { return; } @@ -138,6 +145,80 @@ bool Item::hasImbuementCategoryId(uint16_t categoryId) const { return false; } +double Item::getDodgeChance() const { + if (getTier() == 0) { + return 0; + } + return quadraticPoly( + g_configManager().getFloat(RUSE_CHANCE_FORMULA_A), + g_configManager().getFloat(RUSE_CHANCE_FORMULA_B), + g_configManager().getFloat(RUSE_CHANCE_FORMULA_C), + getTier() + ); +} + +double Item::getFatalChance() const { + if (getTier() == 0) { + return 0; + } + return quadraticPoly( + g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_A), + g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_B), + g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_C), + getTier() + ); +} + +double Item::getMomentumChance() const { + if (getTier() == 0) { + return 0; + } + return quadraticPoly( + g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_A), + g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_B), + g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_C), + getTier() + ); +} + +double Item::getTranscendenceChance() const { + if (getTier() == 0) { + return 0; + } + return quadraticPoly( + g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_A), + g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_B), + g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_C), + getTier() + ); +} + +uint8_t Item::getTier() const { + if (!hasAttribute(ItemAttribute_t::TIER)) { + return 0; + } + + auto tier = getAttribute<uint8_t>(ItemAttribute_t::TIER); + if (tier > g_configManager().getNumber(FORGE_MAX_ITEM_TIER)) { + g_logger().error("{} - Item {} have a wrong tier {}", __FUNCTION__, getName(), tier); + return 0; + } + + return tier; +} + +void Item::setTier(uint8_t tier) { + auto configTier = g_configManager().getNumber(FORGE_MAX_ITEM_TIER); + if (tier > configTier) { + g_logger().error("{} - It is not possible to set a tier higher than {}", __FUNCTION__, configTier); + return; + } + + if (items[id].upgradeClassification) { + setAttribute(ItemAttribute_t::TIER, tier); + } +} + std::shared_ptr<Container> Item::CreateItemAsContainer(const uint16_t type, uint16_t size) { if (const ItemType &it = Item::items[type]; it.id == 0 @@ -151,7 +232,7 @@ std::shared_ptr<Container> Item::CreateItemAsContainer(const uint16_t type, uint return nullptr; } - std::shared_ptr<Container> newItem = std::make_shared<Container>(type, size); + auto newItem = std::make_shared<Container>(type, size); return newItem; } @@ -195,9 +276,9 @@ std::shared_ptr<Item> Item::CreateItem(uint16_t itemId, Position &itemPosition) Item::Item(const uint16_t itemId, uint16_t itemCount /*= 0*/) : id(itemId) { const ItemType &it = items[id]; - auto itemCharges = it.charges; + const auto itemCharges = it.charges; if (it.isFluidContainer() || it.isSplash()) { - auto fluidType = std::clamp<uint16_t>(itemCount, 1, FLUID_INK); + const auto fluidType = std::clamp<uint16_t>(itemCount, 1, FLUID_INK); setAttribute(ItemAttribute_t::FLUIDTYPE, fluidType); } else if (it.stackable) { if (itemCount != 0) { @@ -224,7 +305,7 @@ Item::Item(const std::shared_ptr<Item> &i) : } std::shared_ptr<Item> Item::clone() const { - std::shared_ptr<Item> item = Item::CreateItem(id, count); + const auto &item = Item::CreateItem(id, count); if (item == nullptr) { g_logger().error("[{}] item is nullptr", __FUNCTION__); return nullptr; @@ -237,7 +318,7 @@ std::shared_ptr<Item> Item::clone() const { return item; } -bool Item::equals(std::shared_ptr<Item> compareItem) const { +bool Item::equals(const std::shared_ptr<Item> &compareItem) const { if (!compareItem) { return false; } @@ -282,7 +363,7 @@ void Item::setDefaultSubtype() { setItemCount(1); - auto itemCharges = it.charges; + const auto itemCharges = it.charges; if (itemCharges != 0) { if (it.stackable) { setItemCount(static_cast<uint8_t>(itemCharges)); @@ -305,7 +386,7 @@ void Item::setID(uint16_t newid) { id = newid; const ItemType &it = Item::items[newid]; - uint32_t newDuration = it.decayTime * 1000; + const uint32_t newDuration = it.decayTime * 1000; if (newDuration == 0 && !it.stopTime && it.decayTo < 0) { // We'll get called startDecay anyway so let's schedule it - actually not in all casses @@ -333,15 +414,15 @@ bool Item::isOwner(uint32_t ownerId) const { const auto &player = g_game().getPlayerByID(ownerId); return player && player->getGUID() == getOwnerId(); } - if (auto player = g_game().getPlayerByGUID(ownerId); player) { + if (const auto &player = g_game().getPlayerByGUID(ownerId); player) { return player->getID() == getOwnerId(); } return false; } std::shared_ptr<Cylinder> Item::getTopParent() { - std::shared_ptr<Cylinder> aux = getParent(); - std::shared_ptr<Cylinder> prevaux = std::dynamic_pointer_cast<Cylinder>(shared_from_this()); + auto aux = getParent(); + auto prevaux = std::dynamic_pointer_cast<Cylinder>(shared_from_this()); if (!aux) { return prevaux; } @@ -358,7 +439,7 @@ std::shared_ptr<Cylinder> Item::getTopParent() { } std::shared_ptr<Tile> Item::getTile() { - std::shared_ptr<Cylinder> cylinder = getTopParent(); + auto cylinder = getTopParent(); // get root cylinder if (cylinder && cylinder->getParent()) { cylinder = cylinder->getParent(); @@ -366,6 +447,14 @@ std::shared_ptr<Tile> Item::getTile() { return std::dynamic_pointer_cast<Tile>(cylinder); } +bool Item::isRemoved() { + auto parent = getParent(); + if (parent) { + return parent->isRemoved(); + } + return true; +} + uint16_t Item::getSubType() const { const ItemType &it = items[id]; if (it.isFluidContainer() || it.isSplash()) { @@ -379,7 +468,7 @@ uint16_t Item::getSubType() const { } std::shared_ptr<Player> Item::getHoldingPlayer() { - std::shared_ptr<Cylinder> p = getParent(); + auto p = getParent(); while (p) { if (p->getCreature()) { return p->getCreature()->getPlayer(); @@ -394,7 +483,7 @@ bool Item::isItemStorable() const { if (isStoreItem() || hasOwner()) { return false; } - auto isContainerAndHasSomethingInside = (getContainer() != NULL) && (getContainer()->getItemList().size() > 0); + const auto isContainerAndHasSomethingInside = (getContainer() != nullptr) && (!getContainer()->getItemList().empty()); return (isStowable() || isContainerAndHasSomethingInside); } @@ -771,7 +860,7 @@ Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream &propStream) { return ATTR_READ_ERROR; } - setAttribute(AMOUNT, amount); + setAttribute(ItemAttribute_t::AMOUNT, amount); break; } @@ -819,7 +908,7 @@ Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream &propStream) { return ATTR_READ_ERROR; } - setAttribute(OWNER, ownerId); + setAttribute(ItemAttribute_t::OWNER, ownerId); break; } @@ -843,7 +932,7 @@ Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream &propStream) { bool Item::unserializeAttr(PropStream &propStream) { uint8_t attr_type; while (propStream.read<uint8_t>(attr_type) && attr_type != 0) { - Attr_ReadValue ret = readAttr(static_cast<AttrTypes_t>(attr_type), propStream); + const Attr_ReadValue ret = readAttr(static_cast<AttrTypes_t>(attr_type), propStream); if (ret == ATTR_READ_ERROR) { return false; } else if (ret == ATTR_READ_END) { @@ -859,7 +948,7 @@ bool Item::unserializeItemNode(OTB::Loader &, const OTB::Node &, PropStream &pro void Item::serializeAttr(PropWriteStream &propWriteStream) const { const ItemType &it = items[id]; - if (auto timeStamp = getAttribute<int64_t>(ItemAttribute_t::STORE)) { + if (const auto timeStamp = getAttribute<int64_t>(ItemAttribute_t::STORE)) { propWriteStream.write<uint8_t>(ATTR_STORE); propWriteStream.write<int64_t>(timeStamp); } @@ -868,13 +957,13 @@ void Item::serializeAttr(PropWriteStream &propWriteStream) const { propWriteStream.write<uint8_t>(getSubType()); } - if (auto charges = getAttribute<uint16_t>(ItemAttribute_t::CHARGES)) { + if (const auto charges = getAttribute<uint16_t>(ItemAttribute_t::CHARGES)) { propWriteStream.write<uint8_t>(ATTR_CHARGES); propWriteStream.write<uint16_t>(charges); } if (it.movable) { - if (auto actionId = getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)) { + if (const auto actionId = getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)) { propWriteStream.write<uint8_t>(ATTR_ACTION_ID); propWriteStream.write<uint16_t>(actionId); } @@ -886,7 +975,7 @@ void Item::serializeAttr(PropWriteStream &propWriteStream) const { propWriteStream.writeString(text); } - if (const uint64_t writtenDate = getAttribute<uint64_t>(ItemAttribute_t::DATE)) { + if (const auto writtenDate = getAttribute<uint64_t>(ItemAttribute_t::DATE)) { propWriteStream.write<uint8_t>(ATTR_WRITTENDATE); propWriteStream.write<uint64_t>(writtenDate); } @@ -908,7 +997,7 @@ void Item::serializeAttr(PropWriteStream &propWriteStream) const { propWriteStream.write<int32_t>(getDuration()); } - if (auto decayState = getDecaying(); + if (const auto decayState = getDecaying(); decayState == DECAYING_TRUE || decayState == DECAYING_PENDING) { propWriteStream.write<uint8_t>(ATTR_DECAYING_STATE); propWriteStream.write<uint8_t>(decayState); @@ -989,17 +1078,17 @@ void Item::serializeAttr(PropWriteStream &propWriteStream) const { propWriteStream.write<uint8_t>(getTier()); } - if (hasAttribute(AMOUNT)) { + if (hasAttribute(ItemAttribute_t::AMOUNT)) { propWriteStream.write<uint8_t>(ATTR_AMOUNT); - propWriteStream.write<uint16_t>(getAttribute<uint16_t>(AMOUNT)); + propWriteStream.write<uint16_t>(getAttribute<uint16_t>(ItemAttribute_t::AMOUNT)); } - if (hasAttribute(STORE_INBOX_CATEGORY)) { + if (hasAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY)) { propWriteStream.write<uint8_t>(ATTR_STORE_INBOX_CATEGORY); propWriteStream.writeString(getString(ItemAttribute_t::STORE_INBOX_CATEGORY)); } - if (hasAttribute(OWNER)) { + if (hasAttribute(ItemAttribute_t::OWNER)) { propWriteStream.write<uint8_t>(ATTR_OWNER); propWriteStream.write<uint32_t>(getAttribute<uint32_t>(ItemAttribute_t::OWNER)); } @@ -1025,7 +1114,7 @@ void Item::serializeAttr(PropWriteStream &propWriteStream) const { } } -void Item::setOwner(std::shared_ptr<Creature> owner) { +void Item::setOwner(const std::shared_ptr<Creature> &owner) { auto ownerId = owner->getID(); if (owner->getPlayer()) { ownerId = owner->getPlayer()->getGUID(); @@ -1033,7 +1122,7 @@ void Item::setOwner(std::shared_ptr<Creature> owner) { setOwner(ownerId); } -bool Item::isOwner(std::shared_ptr<Creature> owner) const { +bool Item::isOwner(const std::shared_ptr<Creature> &owner) const { if (!owner) { return false; } @@ -1059,7 +1148,7 @@ std::string Item::getOwnerName() const { return ""; } - auto creature = g_game().getCreatureByID(getOwnerId()); + const auto &creature = g_game().getCreatureByID(getOwnerId()); if (creature) { return creature->getName(); } @@ -1123,15 +1212,27 @@ void Item::checkDecayMapItemOnMove() { } uint32_t Item::getWeight() const { - uint32_t baseWeight = getBaseWeight(); + const uint32_t baseWeight = getBaseWeight(); if (isStackable()) { return baseWeight * std::max<uint32_t>(1, getItemCount()); } return baseWeight; } +int32_t Item::getReflectionFlat(CombatType_t combatType) const { + return items[id].abilities->reflectFlat[combatTypeToIndex(combatType)]; +} + +int32_t Item::getReflectionPercent(CombatType_t combatType) const { + return items[id].abilities->reflectPercent[combatTypeToIndex(combatType)]; +} + +int32_t Item::getSpecializedMagicLevel(CombatType_t combat) const { + return items[id].abilities->specializedMagicLevel[combatTypeToIndex(combat)]; +} + std::vector<std::pair<std::string, std::string>> -Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr*/) { +Item::getDescriptions(const ItemType &it, const std::shared_ptr<Item> &item /*= nullptr*/) { std::ostringstream ss; std::vector<std::pair<std::string, std::string>> descriptions; bool isTradeable = true; @@ -1179,13 +1280,20 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr ss << static_cast<uint16_t>(shootRange) << " fields"; } descriptions.emplace_back("Attack", ss.str()); - } else if (!it.isRanged() && attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - ss.str(""); - ss << attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - descriptions.emplace_back("Attack", ss.str()); - } else { - descriptions.emplace_back("Attack", std::to_string(attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); + } + + if (attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", attack, attackDescription); + } else if (attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(attack); + } + + if (!attackDescription.empty()) { + descriptions.emplace_back("Attack", attackDescription); } } @@ -1251,6 +1359,10 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr skillBoost = true; } + if (it.abilities->regeneration) { + ss << ", faster regeneration"; + } + if (it.abilities->stats[STAT_MAGICPOINTS]) { if (skillBoost) { ss << ", "; @@ -1410,7 +1522,7 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr for (uint8_t i = 0; i < item->getImbuementSlot(); ++i) { slotName = fmt::format("Imbuement Slot {}", i + 1); ss.str(""); - const auto castItem = item; + const auto &castItem = item; if (!castItem) { continue; } @@ -1592,13 +1704,20 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr ss << static_cast<uint16_t>(shootRange) << " fields"; } descriptions.emplace_back("Attack", ss.str()); - } else if (!it.isRanged() && attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - ss.str(""); - ss << attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - descriptions.emplace_back("Attack", ss.str()); - } else { - descriptions.emplace_back("Attack", std::to_string(attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); + } + + if (attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", attack, attackDescription); + } else if (attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(attack); + } + + if (!attackDescription.empty()) { + descriptions.emplace_back("Attack", attackDescription); } } @@ -1905,7 +2024,7 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr<Item> item /*= nullptr return descriptions; } -std::string Item::parseImbuementDescription(std::shared_ptr<Item> item) { +std::string Item::parseImbuementDescription(const std::shared_ptr<Item> &item) { std::ostringstream s; if (item && item->getImbuementSlot() >= 1) { s << std::endl @@ -1927,7 +2046,7 @@ std::string Item::parseImbuementDescription(std::shared_ptr<Item> item) { continue; } - int minutes = imbuementInfo.duration / 60; + const int minutes = imbuementInfo.duration / 60; int hours = minutes / 60; s << fmt::format("{} {} {:02}:{:02}h", baseImbuement->name, imbuementInfo.imbuement->getName(), hours, minutes % 60); } @@ -1942,12 +2061,12 @@ bool Item::isSavedToHouses() { return it.movable || it.isWrappable() || it.isCarpet() || getDoor() || (getContainer() && !getContainer()->empty()) || it.canWriteText || getBed() || it.m_transformOnUse; } -SoundEffect_t Item::getMovementSound(std::shared_ptr<Cylinder> toCylinder) const { +SoundEffect_t Item::getMovementSound(const std::shared_ptr<Cylinder> &toCylinder) const { if (!toCylinder) { return SoundEffect_t::ITEM_MOVE_DEFAULT; } - if (std::shared_ptr<Container> toContainer = toCylinder->getContainer(); + if (const auto &toContainer = toCylinder->getContainer(); toContainer && toContainer->getHoldingPlayer()) { return SoundEffect_t::ITEM_MOVE_BACKPACK; } @@ -2004,7 +2123,7 @@ SoundEffect_t Item::getMovementSound(std::shared_ptr<Cylinder> toCylinder) const return SoundEffect_t::ITEM_MOVE_DEFAULT; } -std::string Item::parseClassificationDescription(std::shared_ptr<Item> item) { +std::string Item::parseClassificationDescription(const std::shared_ptr<Item> &item) { std::ostringstream string; if (item && item->getClassification() >= 1) { string << std::endl @@ -2037,35 +2156,35 @@ std::string Item::parseShowDurationSpeed(int32_t speed, bool &begin) { return description.str(); } -std::string Item::parseShowDuration(std::shared_ptr<Item> item) { +std::string Item::parseShowDuration(const std::shared_ptr<Item> &item) { if (!item) { return {}; } std::ostringstream description; - uint32_t duration = item->getDuration() / 1000; + const uint32_t duration = item->getDuration() / 1000; if (item && item->hasAttribute(ItemAttribute_t::DURATION) && duration > 0) { description << " that will expire in "; if (duration >= 86400) { - uint16_t days = duration / 86400; - uint16_t hours = (duration % 86400) / 3600; + const uint16_t days = duration / 86400; + const uint16_t hours = (duration % 86400) / 3600; description << days << " day" << (days != 1 ? "s" : ""); if (hours > 0) { description << " and " << hours << " hour" << (hours != 1 ? "s" : ""); } } else if (duration >= 3600) { - uint16_t hours = duration / 3600; - uint16_t minutes = (duration % 3600) / 60; + const uint16_t hours = duration / 3600; + const uint16_t minutes = (duration % 3600) / 60; description << hours << " hour" << (hours != 1 ? "s" : ""); if (minutes > 0) { description << " and " << minutes << " minute" << (minutes != 1 ? "s" : ""); } } else if (duration >= 60) { - uint16_t minutes = duration / 60; + const uint16_t minutes = duration / 60; description << minutes << " minute" << (minutes != 1 ? "s" : ""); - uint16_t seconds = duration % 60; + const uint16_t seconds = duration % 60; if (seconds > 0) { description << " and " << seconds << " second" << (seconds != 1 ? "s" : ""); @@ -2080,14 +2199,14 @@ std::string Item::parseShowDuration(std::shared_ptr<Item> item) { return description.str(); } -std::string Item::parseShowAttributesDescription(std::shared_ptr<Item> item, const uint16_t itemId) { +std::string Item::parseShowAttributesDescription(const std::shared_ptr<Item> &item, const uint16_t itemId) { std::ostringstream itemDescription; const ItemType &itemType = Item::items[itemId]; if (itemType.armor != 0 || (item && item->getArmor() != 0) || itemType.showAttributes) { bool begin = itemType.isQuiver() ? false : true; - int32_t armor = (item ? item->getArmor() : itemType.armor); + const int32_t armor = (item ? item->getArmor() : itemType.armor); if (armor != 0) { if (begin) { itemDescription << " (Arm:" << armor; @@ -2114,7 +2233,7 @@ std::string Item::parseShowAttributesDescription(std::shared_ptr<Item> item, con } for (uint8_t i = SKILL_CRITICAL_HIT_CHANCE; i <= SKILL_LAST; i++) { - auto skill = item ? item->getSkill(static_cast<skills_t>(i)) : itemType.getSkill(static_cast<skills_t>(i)); + const auto skill = item ? item->getSkill(static_cast<skills_t>(i)) : itemType.getSkill(static_cast<skills_t>(i)); if (!skill) { continue; } @@ -2308,8 +2427,8 @@ std::string Item::parseShowAttributesDescription(std::shared_ptr<Item> item, con return itemDescription.str(); } -std::string Item::getDescription(const ItemType &it, int32_t lookDistance, std::shared_ptr<Item> item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) { - std::string text = ""; +std::string Item::getDescription(const ItemType &it, int32_t lookDistance, const std::shared_ptr<Item> &item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) { + std::string text; std::ostringstream s; s << getNameDescription(it, item, subType, addArticle); @@ -2320,7 +2439,7 @@ std::string Item::getDescription(const ItemType &it, int32_t lookDistance, std:: if (it.isRune()) { if (it.runeLevel > 0 || it.runeMagLevel > 0) { - if (const auto rune = g_spells().getRuneSpell(it.id)) { + if (const auto &rune = g_spells().getRuneSpell(it.id)) { int32_t tmpSubType = subType; if (item) { tmpSubType = item->getSubType(); @@ -2640,13 +2759,17 @@ std::string Item::getDescription(const ItemType &it, int32_t lookDistance, std:: s << "Vol:" << volume; } } + if (attack != 0) { begin = false; s << " (Atk:" << attack; + } - if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - } + if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0 && !begin) { + s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); + } else if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0 && begin) { + begin = false; + s << " (" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); } if (defense != 0 || extraDefense != 0 || it.isMissile()) { @@ -2679,6 +2802,17 @@ std::string Item::getDescription(const ItemType &it, int32_t lookDistance, std:: s << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; } + if (it.abilities->regeneration) { + if (begin) { + begin = false; + s << " ("; + } else { + s << ", "; + } + + s << "faster regeneration"; + } + for (uint8_t i = SKILL_CRITICAL_HIT_CHANCE; i <= SKILL_LAST; i++) { auto skill = item ? item->getSkill(static_cast<skills_t>(i)) : it.getSkill(static_cast<skills_t>(i)); if (!skill) { @@ -3076,7 +3210,7 @@ std::string Item::getDescription(int32_t lookDistance) { return getDescription(it, lookDistance, getItem()); } -std::string Item::getNameDescription(const ItemType &it, std::shared_ptr<Item> item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) { +std::string Item::getNameDescription(const ItemType &it, const std::shared_ptr<Item> &item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) { if (item) { subType = item->getSubType(); } @@ -3140,9 +3274,9 @@ std::string Item::getWeightDescription(uint32_t weight) const { } std::string Item::getWeightDescription() const { - uint32_t weight = getWeight(); + const uint32_t weight = getWeight(); if (weight == 0) { - return std::string(); + return {}; } return getWeightDescription(weight); } @@ -3227,9 +3361,9 @@ std::shared_ptr<Item> Item::transform(uint16_t itemId, uint16_t itemCount /*= -1 return nullptr; } - std::shared_ptr<Tile> fromTile = cylinder->getTile(); + const auto &fromTile = cylinder->getTile(); if (fromTile) { - auto it = g_game().browseFields.find(fromTile); + const auto it = g_game().browseFields.find(fromTile); if (it != g_game().browseFields.end() && it->second.lock() == cylinder) { cylinder = fromTile; } @@ -3242,8 +3376,8 @@ std::shared_ptr<Item> Item::transform(uint16_t itemId, uint16_t itemCount /*= -1 newItem = Item::CreateItem(itemId, itemCount); } - int32_t itemIndex = cylinder->getThingIndex(static_self_cast<Item>()); - auto duration = getDuration(); + const int32_t itemIndex = cylinder->getThingIndex(static_self_cast<Item>()); + const auto duration = getDuration(); if (duration > 0) { newItem->setDuration(duration); } @@ -3281,16 +3415,17 @@ bool Item::hasMarketAttributes() const { } bool Item::isInsideDepot(bool includeInbox /* = false*/) { - if (std::shared_ptr<Container> thisContainer = getContainer(); thisContainer && (thisContainer->getDepotLocker() || thisContainer->isDepotChest() || (includeInbox && thisContainer->isInbox()))) { + const auto &thisContainer = getContainer(); + if (thisContainer && (thisContainer->getDepotLocker() || thisContainer->isDepotChest() || (includeInbox && thisContainer->isInbox()))) { return true; } - std::shared_ptr<Cylinder> cylinder = getParent(); + const auto &cylinder = getParent(); if (!cylinder) { return false; } - std::shared_ptr<Container> container = cylinder->getContainer(); + auto container = cylinder->getContainer(); if (!container) { return false; } @@ -3307,7 +3442,26 @@ bool Item::isInsideDepot(bool includeInbox /* = false*/) { } void Item::updateTileFlags() { - if (auto tile = getTile()) { + if (const auto &tile = getTile()) { tile->updateTileFlags(static_self_cast<Item>()); } } + +// Custom Attributes + +const std::map<std::string, CustomAttribute, std::less<>> &ItemProperties::getCustomAttributeMap() const { + static std::map<std::string, CustomAttribute, std::less<>> map = {}; + if (!attributePtr) { + return map; + } + return attributePtr->getCustomAttributeMap(); +} + +int32_t ItemProperties::getDuration() const { + ItemDecayState_t decayState = getDecaying(); + if (decayState == DECAYING_TRUE || decayState == DECAYING_STOPPING) { + return std::max<int32_t>(0, getAttribute<int32_t>(ItemAttribute_t::DURATION_TIMESTAMP) - static_cast<int32_t>(OTSYS_TIME())); + } else { + return getAttribute<int32_t>(ItemAttribute_t::DURATION); + } +} diff --git a/src/items/item.hpp b/src/items/item.hpp index aa4f10ec4aa..d199fab15cf 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -9,14 +9,11 @@ #pragma once -#include "items/cylinder.hpp" -#include "items/thing.hpp" #include "enums/item_attribute.hpp" -#include "items/items.hpp" -#include "items/functions/item/attribute.hpp" -#include "lua/scripts/luascript.hpp" -#include "utils/tools.hpp" #include "io/fileloader.hpp" +#include "items/functions/item/attribute.hpp" +#include "items/items.hpp" +#include "items/thing.hpp" class Creature; class Player; @@ -30,6 +27,7 @@ class MagicField; class BedItem; class Imbuement; class Item; +class Cylinder; // This class ItemProperties that serves as an interface to access and modify attributes of an item. The item's attributes are stored in an instance of ItemAttribute. The class ItemProperties has methods to get and set integer and string attributes, check if an attribute exists, remove an attribute, get the underlying attribute bits, and get a vector of attributes. It also has methods to get and set custom attributes, which are stored in a std::map<std::string, CustomAttribute, std::less<>>. The class has a data member attributePtr of type std::unique_ptr<ItemAttribute> that stores a pointer to the item's attributes methods. class ItemProperties { @@ -56,7 +54,7 @@ class ItemProperties { return attributePtr->hasAttribute(type); } - void removeAttribute(ItemAttribute_t type) { + void removeAttribute(ItemAttribute_t type) const { if (attributePtr) { attributePtr->removeAttribute(type); } @@ -76,13 +74,7 @@ class ItemProperties { } // Custom Attributes - const std::map<std::string, CustomAttribute, std::less<>> &getCustomAttributeMap() const { - static std::map<std::string, CustomAttribute, std::less<>> map = {}; - if (!attributePtr) { - return map; - } - return attributePtr->getCustomAttributeMap(); - } + const std::map<std::string, CustomAttribute, std::less<>> &getCustomAttributeMap() const; const CustomAttribute* getCustomAttribute(const std::string &attributeName) const { if (!attributePtr) { return nullptr; @@ -104,7 +96,7 @@ class ItemProperties { return !getCustomAttributeMap().empty(); } - bool removeCustomAttribute(const std::string &attributeName) { + bool removeCustomAttribute(const std::string &attributeName) const { if (!attributePtr) { return false; } @@ -116,14 +108,7 @@ class ItemProperties { return getAttribute<uint16_t>(ItemAttribute_t::CHARGES); } - int32_t getDuration() const { - ItemDecayState_t decayState = getDecaying(); - if (decayState == DECAYING_TRUE || decayState == DECAYING_STOPPING) { - return std::max<int32_t>(0, getAttribute<int32_t>(ItemAttribute_t::DURATION_TIMESTAMP) - static_cast<int32_t>(OTSYS_TIME())); - } else { - return getAttribute<int32_t>(ItemAttribute_t::DURATION); - } - } + int32_t getDuration() const; bool isStoreItem() const { return getAttribute<int64_t>(ItemAttribute_t::STORE) > 0; @@ -215,27 +200,27 @@ class ItemProperties { class Item : virtual public Thing, public ItemProperties, public SharedObject { public: // Factory member to create item of right type based on type - static std::shared_ptr<Item> CreateItem(const uint16_t type, uint16_t count = 0, Position* itemPosition = nullptr); - static std::shared_ptr<Container> CreateItemAsContainer(const uint16_t type, uint16_t size); + static std::shared_ptr<Item> CreateItem(uint16_t type, uint16_t count = 0, Position* itemPosition = nullptr); + static std::shared_ptr<Container> CreateItemAsContainer(uint16_t type, uint16_t size); static std::shared_ptr<Item> CreateItem(uint16_t itemId, Position &itemPosition); static Items items; // Constructor for items - Item(const uint16_t type, uint16_t count = 0); - Item(const std::shared_ptr<Item> &i); + explicit Item(uint16_t type, uint16_t count = 0); + explicit Item(const std::shared_ptr<Item> &i); virtual std::shared_ptr<Item> clone() const; - virtual ~Item() = default; + ~Item() override = default; // non-assignable Item &operator=(const Item &) = delete; - bool equals(std::shared_ptr<Item> compareItem) const; + bool equals(const std::shared_ptr<Item> &compareItem) const; - std::shared_ptr<Item> getItem() override final { + std::shared_ptr<Item> getItem() final { return static_self_cast<Item>(); } - std::shared_ptr<const Item> getItem() const override final { + std::shared_ptr<const Item> getItem() const final { return static_self_cast<Item>(); } virtual std::shared_ptr<Teleport> getTeleport() { @@ -259,13 +244,13 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { bool isSavedToHouses(); - SoundEffect_t getMovementSound(std::shared_ptr<Cylinder> toCylinder) const; + SoundEffect_t getMovementSound(const std::shared_ptr<Cylinder> &toCylinder) const; void setIsLootTrackeable(bool value) { isLootTrackeable = value; } - bool getIsLootTrackeable() { + bool getIsLootTrackeable() const { return isLootTrackeable; } @@ -273,7 +258,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { setAttribute(ItemAttribute_t::OWNER, owner); } - void setOwner(std::shared_ptr<Creature> owner); + void setOwner(const std::shared_ptr<Creature> &owner); virtual uint32_t getOwnerId() const; @@ -281,7 +266,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { std::string getOwnerName() const; - bool isOwner(std::shared_ptr<Creature> owner) const; + bool isOwner(const std::shared_ptr<Creature> &owner) const; bool hasOwner() const { return getOwnerId() != 0; @@ -291,24 +276,24 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { return isStoreItem() || hasOwner(); } - static std::string parseAugmentDescription(std::shared_ptr<Item> item, bool inspect = false) { + static std::string parseAugmentDescription(const std::shared_ptr<Item> &item, bool inspect = false) { if (!item) { return ""; } return items[item->getID()].parseAugmentDescription(inspect); } - static std::string parseImbuementDescription(std::shared_ptr<Item> item); + static std::string parseImbuementDescription(const std::shared_ptr<Item> &item); static std::string parseShowDurationSpeed(int32_t speed, bool &begin); - static std::string parseShowDuration(std::shared_ptr<Item> item); - static std::string parseShowAttributesDescription(std::shared_ptr<Item> item, const uint16_t itemId); - static std::string parseClassificationDescription(std::shared_ptr<Item> item); + static std::string parseShowDuration(const std::shared_ptr<Item> &item); + static std::string parseShowAttributesDescription(const std::shared_ptr<Item> &item, uint16_t itemId); + static std::string parseClassificationDescription(const std::shared_ptr<Item> &item); - static std::vector<std::pair<std::string, std::string>> getDescriptions(const ItemType &it, std::shared_ptr<Item> item = nullptr); - static std::string getDescription(const ItemType &it, int32_t lookDistance, std::shared_ptr<Item> item = nullptr, int32_t subType = -1, bool addArticle = true); - static std::string getNameDescription(const ItemType &it, std::shared_ptr<Item> item = nullptr, int32_t subType = -1, bool addArticle = true); + static std::vector<std::pair<std::string, std::string>> getDescriptions(const ItemType &it, const std::shared_ptr<Item> &item = nullptr); + static std::string getDescription(const ItemType &it, int32_t lookDistance, const std::shared_ptr<Item> &item = nullptr, int32_t subType = -1, bool addArticle = true); + static std::string getNameDescription(const ItemType &it, const std::shared_ptr<Item> &item = nullptr, int32_t subType = -1, bool addArticle = true); static std::string getWeightDescription(const ItemType &it, uint32_t weight, uint32_t count = 1); - std::string getDescription(int32_t lookDistance) override final; + std::string getDescription(int32_t lookDistance) final; std::string getNameDescription(); std::string getWeightDescription() const; @@ -319,10 +304,10 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { virtual void serializeAttr(PropWriteStream &propWriteStream) const; - bool isPushable() override final { + bool isPushable() final { return isMovable(); } - int32_t getThrowRange() const override final { + int32_t getThrowRange() const final { return (isPickupable() ? 15 : 2); } @@ -366,13 +351,9 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { return items[id].abilities->perfectShotRange; } - int32_t getReflectionFlat(CombatType_t combatType) const { - return items[id].abilities->reflectFlat[combatTypeToIndex(combatType)]; - } + int32_t getReflectionFlat(CombatType_t combatType) const; - int32_t getReflectionPercent(CombatType_t combatType) const { - return items[id].abilities->reflectPercent[combatTypeToIndex(combatType)]; - } + int32_t getReflectionPercent(CombatType_t combatType) const; int16_t getMagicShieldCapacityPercent() const { return items[id].abilities->magicShieldCapacityPercent; @@ -382,22 +363,20 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { return items[id].abilities->magicShieldCapacityFlat; } - int32_t getSpecializedMagicLevel(CombatType_t combat) const { - return items[id].abilities->specializedMagicLevel[combatTypeToIndex(combat)]; - } + int32_t getSpecializedMagicLevel(CombatType_t combat) const; int32_t getSpeed() const { - int32_t value = items[id].getSpeed(); + const int32_t value = items[id].getSpeed(); return value; } int32_t getSkill(skills_t skill) const { - int32_t value = items[id].getSkill(skill); + const int32_t value = items[id].getSkill(skill); return value; } int32_t getStat(stats_t stat) const { - int32_t value = items[id].getStat(stat); + const int32_t value = items[id].getStat(stat); return value; } @@ -430,7 +409,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { } std::vector<std::shared_ptr<AugmentInfo>> getAugmentsBySpellNameAndType(const std::string &spellName, Augment_t augmentType) const { std::vector<std::shared_ptr<AugmentInfo>> augments; - for (auto &augment : items[id].augments) { + for (const auto &augment : items[id].augments) { if (strcasecmp(augment->spellName.c_str(), spellName.c_str()) == 0 && augment->type == augmentType) { augments.push_back(augment); } @@ -440,7 +419,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { } std::vector<std::shared_ptr<AugmentInfo>> getAugmentsBySpellName(const std::string &spellName) const { std::vector<std::shared_ptr<AugmentInfo>> augments; - for (auto &augment : items[id].augments) { + for (const auto &augment : items[id].augments) { if (strcasecmp(augment->spellName.c_str(), spellName.c_str()) == 0) { augments.push_back(augment); } @@ -565,7 +544,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { } return items[id].name; } - const std::string getPluralName() const { + std::string getPluralName() const { if (hasAttribute(ItemAttribute_t::PLURALNAME)) { return getString(ItemAttribute_t::PLURALNAME); } @@ -616,7 +595,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { void addUniqueId(uint16_t uniqueId); void setDefaultDuration() { - uint32_t duration = getDefaultDuration(); + const uint32_t duration = getDefaultDuration(); if (duration != 0) { setDuration(duration); } @@ -634,7 +613,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { return true; } virtual void onRemoved(); - virtual void onTradeEvent(TradeEvents_t, std::shared_ptr<Player>) { } + virtual void onTradeEvent(TradeEvents_t, const std::shared_ptr<Player> &) { } virtual void startDecaying(); virtual void stopDecaying(); @@ -662,13 +641,7 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { } std::shared_ptr<Cylinder> getTopParent(); std::shared_ptr<Tile> getTile() override; - bool isRemoved() override { - auto parent = getParent(); - if (parent) { - return parent->isRemoved(); - } - return true; - } + bool isRemoved() override; bool isInsideDepot(bool includeInbox = false); @@ -695,8 +668,8 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { void clearImbuement(uint8_t slot, uint16_t imbuementId) { return setImbuement(slot, imbuementId, 0); } - bool hasImbuementType(ImbuementTypes_t imbuementType, uint16_t imbuementTier) { - auto it = items[id].imbuementTypes.find(imbuementType); + bool hasImbuementType(ImbuementTypes_t imbuementType, uint16_t imbuementTier) const { + const auto it = items[id].imbuementTypes.find(imbuementType); if (it != items[id].imbuementTypes.end()) { return (it->second >= imbuementTier); } @@ -714,78 +687,16 @@ class Item : virtual public Thing, public ItemProperties, public SharedObject { return false; } - double getDodgeChance() const { - if (getTier() == 0) { - return 0; - } - return quadraticPoly( - g_configManager().getFloat(RUSE_CHANCE_FORMULA_A), - g_configManager().getFloat(RUSE_CHANCE_FORMULA_B), - g_configManager().getFloat(RUSE_CHANCE_FORMULA_C), - getTier() - ); - } + double getDodgeChance() const; - double getFatalChance() const { - if (getTier() == 0) { - return 0; - } - return quadraticPoly( - g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_A), - g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_B), - g_configManager().getFloat(ONSLAUGHT_CHANCE_FORMULA_C), - getTier() - ); - } - - double getMomentumChance() const { - if (getTier() == 0) { - return 0; - } - return quadraticPoly( - g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_A), - g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_B), - g_configManager().getFloat(MOMENTUM_CHANCE_FORMULA_C), - getTier() - ); - } - - double getTranscendenceChance() const { - if (getTier() == 0) { - return 0; - } - return quadraticPoly( - g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_A), - g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_B), - g_configManager().getFloat(TRANSCENDANCE_CHANCE_FORMULA_C), - getTier() - ); - } + double getFatalChance() const; - uint8_t getTier() const { - if (!hasAttribute(ItemAttribute_t::TIER)) { - return 0; - } - - auto tier = getAttribute<uint8_t>(ItemAttribute_t::TIER); - if (tier > g_configManager().getNumber(FORGE_MAX_ITEM_TIER)) { - g_logger().error("{} - Item {} have a wrong tier {}", __FUNCTION__, getName(), tier); - return 0; - } + double getMomentumChance() const; - return tier; - } - void setTier(uint8_t tier) { - auto configTier = g_configManager().getNumber(FORGE_MAX_ITEM_TIER); - if (tier > configTier) { - g_logger().error("{} - It is not possible to set a tier higher than {}", __FUNCTION__, configTier); - return; - } + double getTranscendenceChance() const; - if (items[id].upgradeClassification) { - setAttribute(ItemAttribute_t::TIER, tier); - } - } + uint8_t getTier() const; + void setTier(uint8_t tier); uint8_t getClassification() const { return items[id].upgradeClassification; } diff --git a/src/items/items.cpp b/src/items/items.cpp index 43dfeabf2dd..5aaf2129b29 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -7,12 +7,16 @@ * Website: https://docs.opentibiabr.com/ */ -#include "items/functions/item/item_parse.hpp" #include "items/items.hpp" + +#include "config/configmanager.hpp" +#include "game/game.hpp" +#include "items/functions/item/item_parse.hpp" #include "items/weapons/weapons.hpp" #include "lua/creature/movement.hpp" -#include "game/game.hpp" #include "utils/pugicast.hpp" +#include "creatures/combat/spells.hpp" +#include "utils/tools.hpp" #include <appearances.pb.h> @@ -23,7 +27,7 @@ void Items::clear() { ladders.clear(); dummys.clear(); nameToItems.clear(); - g_moveEvents().clear(true); + g_moveEvents().clear(); g_weapons().clear(true); } @@ -57,15 +61,15 @@ LootTypeNames lootTypeNames = { { "unassigned", ITEM_TYPE_UNASSIGNED }, }; -ItemTypes_t Items::getLootType(const std::string &strValue) { - auto lootType = lootTypeNames.find(strValue); +ItemTypes_t Items::getLootType(const std::string &strValue) const { + const auto lootType = lootTypeNames.find(strValue); if (lootType != lootTypeNames.end()) { return lootType->second; } return ITEM_TYPE_NONE; } -const std::string Items::getAugmentNameByType(Augment_t augmentType) { +std::string Items::getAugmentNameByType(Augment_t augmentType) { std::string augmentTypeName = magic_enum::enum_name(augmentType).data(); augmentTypeName = toStartCaseWithSpace(augmentTypeName); if (!isAugmentWithoutValueDescription(augmentType)) { @@ -92,7 +96,7 @@ std::string ItemType::parseAugmentDescription(bool inspect /*= false*/) const { } std::string ItemType::getFormattedAugmentDescription(const std::shared_ptr<AugmentInfo> &augmentInfo) const { - const std::string augmentName = Items::getAugmentNameByType(augmentInfo->type); + const auto augmentName = Items::getAugmentNameByType(augmentInfo->type); std::string augmentSpellNameCapitalized = augmentInfo->spellName; capitalizeWordsIgnoringString(augmentSpellNameCapitalized, " of "); @@ -102,10 +106,23 @@ std::string ItemType::getFormattedAugmentDescription(const std::shared_ptr<Augme return fmt::format("{} -> {}", augmentSpellNameCapitalized, augmentName); } else if (augmentInfo->type == Augment_t::Cooldown) { return fmt::format("{} -> {}{}s {}", augmentSpellNameCapitalized, signal, augmentInfo->value / 1000, augmentName); + } else if (augmentInfo->type == Augment_t::Base) { + const auto &spell = g_spells().getSpellByName(augmentInfo->spellName); + return fmt::format("{} -> {:+}% {} {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName, spell->getGroup() == SPELLGROUP_HEALING ? "healing" : "damage"); } + return fmt::format("{} -> {:+}% {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName); } +void ItemType::addAugment(std::string spellName, Augment_t augmentType, int32_t value) { + auto augmentInfo = std::make_shared<AugmentInfo>(spellName, augmentType, value); + augments.emplace_back(augmentInfo); +} + +void ItemType::setImbuementType(ImbuementTypes_t imbuementType, uint16_t slotMaxTier) { + imbuementTypes[imbuementType] = std::min<uint16_t>(IMBUEMENT_MAX_TIER, slotMaxTier); +} + bool Items::reload() { clear(); loadFromProtobuf(); @@ -153,7 +170,7 @@ void Items::loadFromProtobuf() { // This attribute is only used on 10x protocol, so we should not waste our time iterating it when it's disabled. if (supportAnimation) { for (uint32_t frame_it = 0; frame_it < object.frame_group_size(); ++frame_it) { - FrameGroup objectFrame = object.frame_group(frame_it); + const FrameGroup &objectFrame = object.frame_group(frame_it); if (!objectFrame.has_sprite_info()) { continue; } @@ -243,7 +260,7 @@ bool Items::loadFromXml() { return false; } - for (auto itemNode : doc.child("items").children()) { + for (const auto itemNode : doc.child("items").children()) { if (auto idAttribute = itemNode.attribute("id")) { parseItemNode(itemNode, pugi::cast<uint16_t>(idAttribute.value())); continue; @@ -263,8 +280,8 @@ bool Items::loadFromXml() { continue; } - uint16_t id = pugi::cast<uint16_t>(fromIdAttribute.value()); - uint16_t toId = pugi::cast<uint16_t>(toIdAttribute.value()); + auto id = pugi::cast<uint16_t>(fromIdAttribute.value()); + const auto toId = pugi::cast<uint16_t>(toIdAttribute.value()); while (id <= toId) { parseItemNode(itemNode, id++); } @@ -280,7 +297,7 @@ void Items::buildInventoryList() { } } inventory.shrink_to_fit(); - std::sort(inventory.begin(), inventory.end()); + std::ranges::sort(inventory); } void Items::parseItemNode(const pugi::xml_node &itemNode, uint16_t id) { @@ -299,10 +316,10 @@ void Items::parseItemNode(const pugi::xml_node &itemNode, uint16_t id) { return; } - if (std::string xmlName = itemNode.attribute("name").as_string(); + if (const std::string xmlName = itemNode.attribute("name").as_string(); !xmlName.empty() && itemType.name != xmlName) { if (!itemType.name.empty()) { - if (auto it = std::find_if(nameToItems.begin(), nameToItems.end(), [id](const auto nameMapIt) { + if (const auto it = std::ranges::find_if(nameToItems, [id](const auto nameMapIt) { return nameMapIt.second == id; }); it != nameToItems.end()) { @@ -315,28 +332,28 @@ void Items::parseItemNode(const pugi::xml_node &itemNode, uint16_t id) { } itemType.loaded = true; - pugi::xml_attribute articleAttribute = itemNode.attribute("article"); + const pugi::xml_attribute articleAttribute = itemNode.attribute("article"); if (articleAttribute) { itemType.article = articleAttribute.as_string(); } - pugi::xml_attribute pluralAttribute = itemNode.attribute("plural"); + const pugi::xml_attribute pluralAttribute = itemNode.attribute("plural"); if (pluralAttribute) { itemType.pluralName = pluralAttribute.as_string(); } - for (auto attributeNode : itemNode.children()) { - pugi::xml_attribute keyAttribute = attributeNode.attribute("key"); + for (const auto &attributeNode : itemNode.children()) { + const pugi::xml_attribute keyAttribute = attributeNode.attribute("key"); if (!keyAttribute) { continue; } - pugi::xml_attribute valueAttribute = attributeNode.attribute("value"); + const pugi::xml_attribute valueAttribute = attributeNode.attribute("value"); if (!valueAttribute) { continue; } - std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string()); + const std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string()); auto parseAttribute = ItemParseAttributesMap.find(tmpStrValue); if (parseAttribute != ItemParseAttributesMap.end()) { ItemParse::initParse(tmpStrValue, attributeNode, valueAttribute, itemType); @@ -366,7 +383,7 @@ const ItemType &Items::getItemType(size_t id) const { } uint16_t Items::getItemIdByName(const std::string &name) { - auto result = nameToItems.find(asLowerCaseString(name)); + const auto result = nameToItems.find(asLowerCaseString(name)); if (result == nameToItems.end()) { return 0; @@ -381,3 +398,19 @@ bool Items::hasItemType(size_t hasId) const { } return false; } + +uint32_t Abilities::getHealthGain() const { + return healthGain * g_configManager().getFloat(RATE_HEALTH_REGEN); +} + +uint32_t Abilities::getHealthTicks() const { + return healthTicks / g_configManager().getFloat(RATE_HEALTH_REGEN_SPEED); +} + +uint32_t Abilities::getManaGain() const { + return manaGain * g_configManager().getFloat(RATE_MANA_REGEN); +} + +uint32_t Abilities::getManaTicks() const { + return manaTicks / g_configManager().getFloat(RATE_MANA_REGEN_SPEED); +} diff --git a/src/items/items.hpp b/src/items/items.hpp index 0d6f692d308..b977f0bf7a9 100644 --- a/src/items/items.hpp +++ b/src/items/items.hpp @@ -9,13 +9,13 @@ #pragma once -#include "config/configmanager.hpp" -#include "utils/utils_definitions.hpp" -#include "declarations.hpp" +#include "creatures/creatures_definitions.hpp" #include "game/movement/position.hpp" +#include "items/items_definitions.hpp" +#include "utils/utils_definitions.hpp" +#include "enums/item_attribute.hpp" struct Abilities { -public: std::array<ConditionType_t, ConditionType_t::CONDITION_COUNT> conditionImmunities = {}; std::array<ConditionType_t, ConditionType_t::CONDITION_COUNT> conditionSuppressions = {}; @@ -65,35 +65,26 @@ struct Abilities { healthGain = value; } - uint32_t getHealthGain() const { - return healthGain * g_configManager().getFloat(RATE_HEALTH_REGEN); - } + uint32_t getHealthGain() const; void setHealthTicks(uint32_t value) { healthTicks = value; } - uint32_t getHealthTicks() const { - return healthTicks / g_configManager().getFloat(RATE_HEALTH_REGEN_SPEED); - } + uint32_t getHealthTicks() const; void setManaGain(uint32_t value) { manaGain = value; } - uint32_t getManaGain() const { - return manaGain * g_configManager().getFloat(RATE_MANA_REGEN); - } + uint32_t getManaGain() const; void setManaTicks(uint32_t value) { manaTicks = value; } - uint32_t getManaTicks() const { - return manaTicks / g_configManager().getFloat(RATE_MANA_REGEN_SPEED); - } + uint32_t getManaTicks() const; -private: uint32_t healthGain = 0; uint32_t healthTicks = 0; uint32_t manaGain = 0; @@ -110,7 +101,7 @@ class ItemType { ItemType(const ItemType &other) = delete; ItemType &operator=(const ItemType &other) = delete; - ItemType(ItemType &&other) = default; + ItemType(ItemType &&other) noexcept = default; ItemType &operator=(ItemType &&other) = default; bool isGroundTile() const { @@ -255,14 +246,9 @@ class ItemType { std::string parseAugmentDescription(bool inspect = false) const; std::string getFormattedAugmentDescription(const std::shared_ptr<AugmentInfo> &augmentInfo) const; - void addAugment(std::string spellName, Augment_t augmentType, int32_t value) { - auto augmentInfo = std::make_shared<AugmentInfo>(spellName, augmentType, value); - augments.emplace_back(augmentInfo); - } + void addAugment(std::string spellName, Augment_t augmentType, int32_t value); - void setImbuementType(ImbuementTypes_t imbuementType, uint16_t slotMaxTier) { - imbuementTypes[imbuementType] = std::min<uint16_t>(IMBUEMENT_MAX_TIER, slotMaxTier); - } + void setImbuementType(ImbuementTypes_t imbuementType, uint16_t slotMaxTier); ItemGroup_t group = ITEM_GROUP_NONE; ItemTypes_t type = ITEM_TYPE_NONE; @@ -415,7 +401,7 @@ class Items { uint16_t getItemIdByName(const std::string &name); - ItemTypes_t getLootType(const std::string &strValue); + ItemTypes_t getLootType(const std::string &strValue) const; bool loadFromXml(); void parseItemNode(const pugi::xml_node &itemNode, uint16_t id); @@ -445,7 +431,7 @@ class Items { return dummys; } - static const std::string getAugmentNameByType(Augment_t augmentType); + static std::string getAugmentNameByType(Augment_t augmentType); static bool isAugmentWithoutValueDescription(Augment_t augmentType) { static std::vector<Augment_t> vector = { @@ -454,7 +440,7 @@ class Items { Augment_t::StrongImpact, }; - return std::find(vector.begin(), vector.end(), augmentType) != vector.end(); + return std::ranges::find(vector, augmentType) != vector.end(); } private: diff --git a/src/items/items_classification.hpp b/src/items/items_classification.hpp index 601abd328ed..54521fd7675 100644 --- a/src/items/items_classification.hpp +++ b/src/items/items_classification.hpp @@ -17,7 +17,7 @@ struct TierInfo { }; // Classification class for forging system and market. -class ItemClassification { +class ItemClassification final { public: ItemClassification() = default; explicit ItemClassification(uint8_t id) : @@ -32,6 +32,6 @@ class ItemClassification { table.convergenceTransferPrice = convergenceTransferPrice; } - uint8_t id; - std::map<uint8_t, TierInfo> tiers; + uint8_t id {}; + std::map<uint8_t, TierInfo> tiers {}; }; diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp index 7968e5cd705..9b6990c0cb7 100644 --- a/src/items/items_definitions.hpp +++ b/src/items/items_definitions.hpp @@ -140,34 +140,35 @@ enum ItemGroup_t { enum ItemTypes_t { ITEM_TYPE_NONE, - // Odered to make the cast from protobuf::itemCategory to ItemTypes_t easier. + // Ordered to make the cast from protobuf::itemCategory to ItemTypes_t easier. // Do not edit it from Start-End // Start - ITEM_TYPE_ARMOR, - ITEM_TYPE_AMULET, - ITEM_TYPE_BOOTS, - ITEM_TYPE_CONTAINER, - ITEM_TYPE_DECORATION, - ITEM_TYPE_FOOD, - ITEM_TYPE_HELMET, - ITEM_TYPE_LEGS, - ITEM_TYPE_OTHER, - ITEM_TYPE_POTION, - ITEM_TYPE_RING, - ITEM_TYPE_RUNE, - ITEM_TYPE_SHIELD, - ITEM_TYPE_TOOLS, - ITEM_TYPE_VALUABLE, - ITEM_TYPE_AMMO, - ITEM_TYPE_AXE, - ITEM_TYPE_CLUB, - ITEM_TYPE_DISTANCE, - ITEM_TYPE_SWORD, - ITEM_TYPE_WAND, - ITEM_TYPE_PREMIUMSCROLL, - ITEM_TYPE_TIBIACOIN, - ITEM_TYPE_CREATUREPRODUCT, - ITEM_TYPE_QUIVER, + ITEM_TYPE_ARMOR = 1, + ITEM_TYPE_AMULET = 2, + ITEM_TYPE_BOOTS = 3, + ITEM_TYPE_CONTAINER = 4, + ITEM_TYPE_DECORATION = 5, + ITEM_TYPE_FOOD = 6, + ITEM_TYPE_HELMET = 7, + ITEM_TYPE_LEGS = 8, + ITEM_TYPE_OTHER = 9, + ITEM_TYPE_POTION = 10, + ITEM_TYPE_RING = 11, + ITEM_TYPE_RUNE = 12, + ITEM_TYPE_SHIELD = 13, + ITEM_TYPE_TOOLS = 14, + ITEM_TYPE_VALUABLE = 15, + ITEM_TYPE_AMMO = 16, + ITEM_TYPE_AXE = 17, + ITEM_TYPE_CLUB = 18, + ITEM_TYPE_DISTANCE = 19, + ITEM_TYPE_SWORD = 20, + ITEM_TYPE_WAND = 21, + ITEM_TYPE_PREMIUMSCROLL = 22, + ITEM_TYPE_TIBIACOIN = 23, + ITEM_TYPE_CREATUREPRODUCT = 24, + ITEM_TYPE_QUIVER = 25, + ITEM_TYPE_SOULCORES = 26, // End ITEM_TYPE_DEPOT, @@ -272,6 +273,7 @@ enum ImbuementTypes_t : int64_t { enum class Augment_t : uint8_t { None, + Base, PowerfulImpact, StrongImpact, IncreasedDamage, @@ -458,7 +460,7 @@ enum TileFlags_t : uint32_t { TILESTATE_FLOORCHANGE = TILESTATE_FLOORCHANGE_DOWN | TILESTATE_FLOORCHANGE_NORTH | TILESTATE_FLOORCHANGE_SOUTH | TILESTATE_FLOORCHANGE_EAST | TILESTATE_FLOORCHANGE_WEST | TILESTATE_FLOORCHANGE_SOUTH_ALT | TILESTATE_FLOORCHANGE_EAST_ALT, }; -enum ZoneType_t { +enum ZoneType_t : uint8_t { ZONE_PROTECTION, ZONE_NOPVP, ZONE_PVP, @@ -621,7 +623,7 @@ enum ItemParseAttributes_t { }; struct ImbuementInfo { - Imbuement* imbuement; + Imbuement* imbuement {}; uint32_t duration = 0; }; @@ -629,7 +631,7 @@ struct AugmentInfo { AugmentInfo(std::string spellName, Augment_t type, int32_t value) : spellName(std::move(spellName)), type(type), value(value) { } - std::string spellName; + std::string spellName {}; Augment_t type; - int32_t value; + int32_t value {}; }; diff --git a/src/items/thing.cpp b/src/items/thing.cpp index 647f312b227..4c2f1d5a88c 100644 --- a/src/items/thing.cpp +++ b/src/items/thing.cpp @@ -8,10 +8,11 @@ */ #include "items/thing.hpp" + #include "items/tile.hpp" const Position &Thing::getPosition() { - std::shared_ptr<Tile> tile = getTile(); + const auto &tile = getTile(); if (!tile) { return Tile::nullptr_tile->getPosition(); } diff --git a/src/items/tile.cpp b/src/items/tile.cpp index 40d3ce86a19..edd827db0e5 100644 --- a/src/items/tile.cpp +++ b/src/items/tile.cpp @@ -8,18 +8,22 @@ */ #include "items/tile.hpp" -#include "creatures/creature.hpp" + +#include "config/configmanager.hpp" #include "creatures/combat/combat.hpp" +#include "creatures/creature.hpp" +#include "creatures/monsters/monster.hpp" +#include "creatures/players/player.hpp" +#include "enums/account_type.hpp" #include "game/game.hpp" +#include "game/movement/teleport.hpp" #include "game/zones/zone.hpp" #include "items/containers/mailbox/mailbox.hpp" -#include "creatures/monsters/monster.hpp" -#include "lua/creature/movement.hpp" -#include "game/movement/teleport.hpp" #include "items/trashholder.hpp" -#include "io/iomap.hpp" +#include "lua/creature/movement.hpp" #include "map/spectators.hpp" -#include "enums/account_type.hpp" +#include "utils/tools.hpp" +#include "game/scheduling/dispatcher.hpp" auto real_nullptr_tile = std::make_shared<StaticTile>(0xFFFF, 0xFFFF, 0xFF); const std::shared_ptr<Tile> &Tile::nullptr_tile = real_nullptr_tile; @@ -55,7 +59,7 @@ bool Tile::hasProperty(ItemProperty prop) const { } } -bool Tile::hasProperty(std::shared_ptr<Item> exclude, ItemProperty prop) const { +bool Tile::hasProperty(const std::shared_ptr<Item> &exclude, ItemProperty prop) const { if (!exclude) { g_logger().error("[{}]: exclude is nullptr", __FUNCTION__); return false; @@ -68,7 +72,7 @@ bool Tile::hasProperty(std::shared_ptr<Item> exclude, ItemProperty prop) const { } if (const TileItemVector* items = getItemList()) { - for (auto &item : *items) { + for (const auto &item : *items) { if (!item) { g_logger().error("Tile::hasProperty: tile {} has an item which is nullptr", tilePos.toString()); continue; @@ -82,6 +86,10 @@ bool Tile::hasProperty(std::shared_ptr<Item> exclude, ItemProperty prop) const { return false; } +bool Tile::hasFlag(uint32_t flag) const { + return hasBitSet(flag, this->flags); +} + bool Tile::hasHeight(uint32_t n) const { uint32_t height = 0; @@ -96,7 +104,7 @@ bool Tile::hasHeight(uint32_t n) const { } if (const TileItemVector* items = getItemList()) { - for (auto &item : *items) { + for (const auto &item : *items) { if (item->hasProperty(CONST_PROP_HASHEIGHT)) { ++height; } @@ -147,9 +155,9 @@ std::shared_ptr<Teleport> Tile::getTeleportItem() const { } if (const TileItemVector* items = getItemList()) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getTeleport()) { - return (*it)->getTeleport(); + for (const auto &item : std::ranges::reverse_view(*items)) { + if (item->getTeleport()) { + return item->getTeleport(); } } } @@ -166,9 +174,9 @@ std::shared_ptr<MagicField> Tile::getFieldItem() const { } if (const TileItemVector* items = getItemList()) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getMagicField()) { - return (*it)->getMagicField(); + for (const auto &item : std::ranges::reverse_view(*items)) { + if (item->getMagicField()) { + return item->getMagicField(); } } } @@ -185,9 +193,9 @@ std::shared_ptr<TrashHolder> Tile::getTrashHolder() const { } if (const TileItemVector* items = getItemList()) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getTrashHolder()) { - return (*it)->getTrashHolder(); + for (const auto &item : std::ranges::reverse_view(*items)) { + if (item->getTrashHolder()) { + return item->getTrashHolder(); } } } @@ -204,9 +212,9 @@ std::shared_ptr<Mailbox> Tile::getMailbox() const { } if (const TileItemVector* items = getItemList()) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getMailbox()) { - return (*it)->getMailbox(); + for (const auto &item : std::ranges::reverse_view(*items)) { + if (item->getMailbox()) { + return item->getMailbox(); } } } @@ -223,9 +231,9 @@ std::shared_ptr<BedItem> Tile::getBedItem() const { } if (const TileItemVector* items = getItemList()) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getBed()) { - return (*it)->getBed(); + for (const auto &item : std::ranges::reverse_view(*items)) { + if (item->getBed()) { + return item->getBed(); } } } @@ -250,23 +258,23 @@ std::shared_ptr<Creature> Tile::getBottomCreature() const { return nullptr; } -std::shared_ptr<Creature> Tile::getTopVisibleCreature(std::shared_ptr<Creature> creature) const { +std::shared_ptr<Creature> Tile::getTopVisibleCreature(const std::shared_ptr<Creature> &creature) const { if (const CreatureVector* creatures = getCreatures()) { if (creature) { - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player && player->isAccessPlayer()) { return getTopCreature(); } - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (creature->canSeeCreature(tileCreature)) { return tileCreature; } } } else { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (!tileCreature->isInvisible()) { - std::shared_ptr<Player> player = tileCreature->getPlayer(); + const auto &player = tileCreature->getPlayer(); if (!player || !player->isInGhostMode()) { return tileCreature; } @@ -277,25 +285,25 @@ std::shared_ptr<Creature> Tile::getTopVisibleCreature(std::shared_ptr<Creature> return nullptr; } -std::shared_ptr<Creature> Tile::getBottomVisibleCreature(std::shared_ptr<Creature> creature) const { +std::shared_ptr<Creature> Tile::getBottomVisibleCreature(const std::shared_ptr<Creature> &creature) const { if (const CreatureVector* creatures = getCreatures()) { if (creature) { - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player && player->isAccessPlayer()) { return getBottomCreature(); } - for (auto it = creatures->rbegin(), end = creatures->rend(); it != end; ++it) { - if (creature->canSeeCreature(*it)) { - return *it; + for (const auto &reverseCreature : std::ranges::reverse_view(*creatures)) { + if (creature->canSeeCreature(reverseCreature)) { + return reverseCreature; } } } else { - for (auto it = creatures->rbegin(), end = creatures->rend(); it != end; ++it) { - if (!(*it)->isInvisible()) { - std::shared_ptr<Player> player = (*it)->getPlayer(); + for (const auto &reverseCreature : std::ranges::reverse_view(*creatures)) { + if (!reverseCreature->isInvisible()) { + const auto &player = reverseCreature->getPlayer(); if (!player || !player->isInGhostMode()) { - return *it; + return reverseCreature; } } } @@ -334,8 +342,8 @@ std::shared_ptr<Item> Tile::getItemByTopOrder(int32_t topOrder) { return nullptr; } -std::shared_ptr<Thing> Tile::getTopVisibleThing(std::shared_ptr<Creature> creature) { - std::shared_ptr<Thing> thing = getTopVisibleCreature(creature); +std::shared_ptr<Thing> Tile::getTopVisibleThing(const std::shared_ptr<Creature> &creature) { + const auto &thing = getTopVisibleCreature(creature); if (thing) { return thing; } @@ -360,11 +368,16 @@ std::shared_ptr<Thing> Tile::getTopVisibleThing(std::shared_ptr<Creature> creatu return ground; } -void Tile::onAddTileItem(std::shared_ptr<Item> item) { +void Tile::onAddTileItem(const std::shared_ptr<Item> &item) { + if (!item) { + g_logger().error("Tile::onAddTileItem: item is nullptr"); + return; + } + if ((item->hasProperty(CONST_PROP_MOVABLE) || item->getContainer()) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH))) { - auto it = g_game().browseFields.find(static_self_cast<Tile>()); + const auto it = g_game().browseFields.find(static_self_cast<Tile>()); if (it != g_game().browseFields.end()) { - auto lockedCylinder = it->second.lock(); + const auto &lockedCylinder = it->second.lock(); if (lockedCylinder) { lockedCylinder->addItemBack(item); item->setParent(getTile()); @@ -376,7 +389,7 @@ void Tile::onAddTileItem(std::shared_ptr<Item> item) { const Position &cylinderMapPos = getPosition(); - auto spectators = Spectators().find<Creature>(cylinderMapPos, true); + const auto spectators = Spectators().find<Creature>(cylinderMapPos, true); // send to client for (const auto &spectator : spectators) { @@ -401,7 +414,7 @@ void Tile::onAddTileItem(std::shared_ptr<Item> item) { if (getTopTopItem() && getTopTopItem()->canReceiveAutoCarpet()) { return; } - auto house = getHouse(); + const auto &house = getHouse(); if (!house) { return; } @@ -410,36 +423,41 @@ void Tile::onAddTileItem(std::shared_ptr<Item> item) { if (!tile || !tile->getGround() || tile->getGround()->getID() != getGround()->getID()) { continue; } - auto topItem = tile->getTopTopItem(); + const auto &topItem = tile->getTopTopItem(); if (!topItem || !topItem->canReceiveAutoCarpet()) { continue; } // Check if tile is part of the same house - if (auto tileHouse = tile->getHouse(); !tileHouse || house != tileHouse) { + if (const auto &tileHouse = tile->getHouse(); !tileHouse || house != tileHouse) { continue; } // Clear any existing carpet - for (auto tileItem : *tile->getItemList()) { + for (const auto &tileItem : *tile->getItemList()) { if (tileItem && tileItem->isCarpet()) { tile->removeThing(tileItem, tileItem->getItemCount()); } } - auto carpet = item->clone(); + const auto &carpet = item->clone(); carpet->setAttribute(ItemAttribute_t::ACTIONID, IMMOVABLE_ACTION_ID); tile->addThing(carpet); } } } -void Tile::onUpdateTileItem(std::shared_ptr<Item> oldItem, const ItemType &oldType, std::shared_ptr<Item> newItem, const ItemType &newType) { +void Tile::onUpdateTileItem(const std::shared_ptr<Item> &oldItem, const ItemType &oldType, const std::shared_ptr<Item> &newItem, const ItemType &newType) { + if (!oldItem || !newItem) { + g_logger().error("Tile::onUpdateTileItem: oldItem or newItem is nullptr"); + return; + } + if ((newItem->hasProperty(CONST_PROP_MOVABLE) || newItem->getContainer()) || (newItem->isWrapable() && newItem->hasProperty(CONST_PROP_MOVABLE) && !oldItem->hasProperty(CONST_PROP_BLOCKPATH))) { - auto it = g_game().browseFields.find(getTile()); + const auto it = g_game().browseFields.find(getTile()); if (it != g_game().browseFields.end()) { - auto lockedCylinder = it->second.lock(); + const auto &lockedCylinder = it->second.lock(); if (lockedCylinder) { - int32_t index = lockedCylinder->getThingIndex(oldItem); + const int32_t index = lockedCylinder->getThingIndex(oldItem); if (index != -1) { lockedCylinder->replaceThing(index, newItem); newItem->setParent(static_self_cast<Tile>()); @@ -447,11 +465,11 @@ void Tile::onUpdateTileItem(std::shared_ptr<Item> oldItem, const ItemType &oldTy } } } else if ((oldItem->hasProperty(CONST_PROP_MOVABLE) || oldItem->getContainer()) || (oldItem->isWrapable() && !oldItem->hasProperty(CONST_PROP_MOVABLE) && !oldItem->hasProperty(CONST_PROP_BLOCKPATH))) { - auto it = g_game().browseFields.find(getTile()); + const auto it = g_game().browseFields.find(getTile()); if (it != g_game().browseFields.end()) { - auto lockedCylinder = it->second.lock(); + const auto &lockedCylinder = it->second.lock(); if (lockedCylinder) { - std::shared_ptr<Cylinder> oldParent = oldItem->getParent(); + const auto &oldParent = oldItem->getParent(); lockedCylinder->removeThing(oldItem, oldItem->getItemCount()); oldItem->setParent(oldParent); } @@ -460,7 +478,7 @@ void Tile::onUpdateTileItem(std::shared_ptr<Item> oldItem, const ItemType &oldTy const Position &cylinderMapPos = getPosition(); - auto spectators = Spectators().find<Creature>(cylinderMapPos, true); + const auto spectators = Spectators().find<Creature>(cylinderMapPos, true); // send to client for (const auto &spectator : spectators) { @@ -475,17 +493,22 @@ void Tile::onUpdateTileItem(std::shared_ptr<Item> oldItem, const ItemType &oldTy } } -void Tile::onRemoveTileItem(const CreatureVector &spectators, const std::vector<int32_t> &oldStackPosVector, std::shared_ptr<Item> item) { +void Tile::onRemoveTileItem(const CreatureVector &spectators, const std::vector<int32_t> &oldStackPosVector, const std::shared_ptr<Item> &item) { + if (!item) { + g_logger().error("Tile::onRemoveTileItem: item is nullptr"); + return; + } + if ((item->hasProperty(CONST_PROP_MOVABLE) || item->getContainer()) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH))) { - auto it = g_game().browseFields.find(getTile()); + const auto it = g_game().browseFields.find(getTile()); if (it != g_game().browseFields.end()) { - auto lockedCylinder = it->second.lock(); + const auto &lockedCylinder = it->second.lock(); if (lockedCylinder) { lockedCylinder->removeThing(item, item->getItemCount()); } } } - for (auto &zone : getZones()) { + for (const auto &zone : getZones()) { zone->itemRemoved(item); } @@ -496,26 +519,26 @@ void Tile::onRemoveTileItem(const CreatureVector &spectators, const std::vector< // send to client size_t i = 0; - for (std::shared_ptr<Creature> spectator : spectators) { - if (std::shared_ptr<Player> tmpPlayer = spectator->getPlayer()) { + for (const auto &spectator : spectators) { + if (const auto &tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendRemoveTileThing(cylinderMapPos, oldStackPosVector[i++]); } } // event methods - for (std::shared_ptr<Creature> spectator : spectators) { + for (const auto &spectator : spectators) { spectator->onRemoveTileItem(static_self_cast<Tile>(), cylinderMapPos, iType, item); } if (!hasFlag(TILESTATE_PROTECTIONZONE) || g_configManager().getBoolean(CLEAN_PROTECTION_ZONES)) { - auto items = getItemList(); + const auto &items = getItemList(); if (!items || items->empty()) { g_game().removeTileToClean(static_self_cast<Tile>()); return; } bool ret = false; - for (auto toCheck : *items) { + for (const auto &toCheck : *items) { if (toCheck->isCleanable()) { ret = true; break; @@ -531,7 +554,7 @@ void Tile::onRemoveTileItem(const CreatureVector &spectators, const std::vector< if (getTopTopItem() && getTopTopItem()->canReceiveAutoCarpet()) { return; } - auto house = getHouse(); + const auto &house = getHouse(); if (!house) { return; } @@ -540,16 +563,16 @@ void Tile::onRemoveTileItem(const CreatureVector &spectators, const std::vector< if (!tile || !tile->getGround() || tile->getGround()->getID() != getGround()->getID()) { continue; } - auto topItem = tile->getTopTopItem(); + const auto &topItem = tile->getTopTopItem(); if (!topItem || !topItem->canReceiveAutoCarpet()) { continue; } // Check if tile is part of the same house - if (auto tileHouse = tile->getHouse(); !tileHouse || house != tileHouse) { + if (const auto &tileHouse = tile->getHouse(); !tileHouse || house != tileHouse) { continue; } - for (auto tileItem : *tile->getItemList()) { + for (const auto &tileItem : *tile->getItemList()) { if (tileItem && tileItem->getID() == item->getID()) { tile->removeThing(tileItem, tileItem->getItemCount()); } @@ -562,19 +585,23 @@ void Tile::onUpdateTile(const CreatureVector &spectators) { const Position &cylinderMapPos = getPosition(); // send to clients - for (std::shared_ptr<Creature> spectator : spectators) { + for (const auto &spectator : spectators) { spectator->getPlayer()->sendUpdateTile(getTile(), cylinderMapPos); } } -ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t tileFlags, std::shared_ptr<Creature>) { +ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t tileFlags, const std::shared_ptr<Creature> &) { + if (!thing) { + return RETURNVALUE_NOTPOSSIBLE; + } + if (hasBitSet(FLAG_NOLIMIT, tileFlags)) { return RETURNVALUE_NOERROR; } - if (auto creature = thing->getCreature()) { + if (const auto &creature = thing->getCreature()) { if (creature->getNpc()) { - ReturnValue returnValue = checkNpcCanWalkIntoTile(); + const ReturnValue returnValue = checkNpcCanWalkIntoTile(); if (returnValue != RETURNVALUE_NOERROR) { return returnValue; } @@ -588,7 +615,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ return RETURNVALUE_NOTPOSSIBLE; } - if (std::shared_ptr<Monster> monster = creature->getMonster()) { + if (const auto &monster = creature->getMonster()) { if (hasFlag(TILESTATE_PROTECTIONZONE | TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT) && (!monster->isFamiliar() || (monster->isFamiliar() && monster->getMaster() && monster->getMaster()->getAttackedCreature()))) { return RETURNVALUE_NOTPOSSIBLE; } @@ -602,19 +629,19 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ const CreatureVector* creatures = getCreatures(); if (monster->canPushCreatures() && !monster->isSummon()) { if (creatures) { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (tileCreature->getPlayer() && tileCreature->getPlayer()->isInGhostMode()) { continue; } - std::shared_ptr<Monster> creatureMonster = tileCreature->getMonster(); + const auto &creatureMonster = tileCreature->getMonster(); if (!creatureMonster || !tileCreature->isPushable() || (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) { return RETURNVALUE_NOTPOSSIBLE; } } } } else if (creatures && !creatures->empty()) { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (!tileCreature->isInGhostMode()) { return RETURNVALUE_NOTENOUGHROOM; } @@ -636,7 +663,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } if (hasHarmfulField()) { - CombatType_t combatType = getFieldItem()->getCombatType(); + const CombatType_t combatType = getFieldItem()->getCombatType(); // There is 3 options for a monster to enter a magic field // 1) Monster is immune @@ -657,9 +684,9 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } const CreatureVector* creatures = getCreatures(); - if (std::shared_ptr<Player> player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, tileFlags) && !player->isAccessPlayer()) { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (!player->canWalkthrough(tileCreature)) { return RETURNVALUE_NOTPOSSIBLE; } @@ -680,7 +707,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ if (playerTile && playerTile->hasFlag(TILESTATE_PROTECTIONZONE)) { auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT); if (maxOnline > 1 && player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER && !hasFlag(TILESTATE_PROTECTIONZONE)) { - auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT); + const auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT); auto accountPlayers = g_game().getPlayersByAccount(player->getAccount()); int countOutsizePZ = 0; for (const auto &accountPlayer : accountPlayers) { @@ -714,7 +741,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } } } else if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, tileFlags)) { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (!tileCreature->isInGhostMode()) { return RETURNVALUE_NOTENOUGHROOM; } @@ -727,7 +754,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ // NO PVP magic wall or wild growth field check if (creature && creature->getPlayer()) { if (const auto fieldList = getItemList()) { - for (auto &findfield : *fieldList) { + for (const auto &findfield : *fieldList) { if (findfield && (findfield->getID() == ITEM_WILDGROWTH_SAFE || findfield->getID() == ITEM_MAGICWALL_SAFE)) { if (!creature->isInGhostMode()) { g_game().internalRemoveItem(findfield, 1); @@ -749,7 +776,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } if (const auto items = getItemList()) { - for (auto &item : *items) { + for (const auto &item : *items) { const ItemType &iiType = Item::items[item->getID()]; if (iiType.blockSolid && (!iiType.movable || item->hasAttribute(ItemAttribute_t::UNIQUEID))) { return RETURNVALUE_NOTPOSSIBLE; @@ -757,20 +784,20 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } } } - } else if (auto item = thing->getItem()) { + } else if (const auto &item = thing->getItem()) { const TileItemVector* items = getItemList(); if (items && items->size() >= 0x3E8) { return RETURNVALUE_NOTPOSSIBLE; } - bool itemIsHangable = item->isHangable(); + const bool itemIsHangable = item->isHangable(); if (ground == nullptr && !itemIsHangable) { return RETURNVALUE_NOTPOSSIBLE; } const CreatureVector* creatures = getCreatures(); if (creatures && !creatures->empty() && item->isBlocking() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, tileFlags)) { - for (auto &tileCreature : *creatures) { + for (const auto &tileCreature : *creatures) { if (!tileCreature->isInGhostMode()) { return RETURNVALUE_NOTENOUGHROOM; } @@ -779,7 +806,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { if (items) { - for (auto &tileItem : *items) { + for (const auto &tileItem : *items) { if (tileItem->isHangable()) { return RETURNVALUE_NEEDEXCHANGE; } @@ -802,7 +829,7 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_ } if (items) { - for (auto &tileItem : *items) { + for (const auto &tileItem : *items) { const ItemType &iiType = Item::items[tileItem->getID()]; if (!iiType.blockSolid || iiType.type == ITEM_TYPE_TRASHHOLDER) { continue; @@ -843,13 +870,17 @@ ReturnValue Tile::queryMaxCount(int32_t, const std::shared_ptr<Thing> &, uint32_ return RETURNVALUE_NOERROR; } -ReturnValue Tile::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, std::shared_ptr<Creature> /*= nullptr */) { - int32_t index = getThingIndex(thing); +ReturnValue Tile::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, const std::shared_ptr<Creature> & /*= nullptr */) { + if (!thing) { + return RETURNVALUE_NOTPOSSIBLE; + } + + const int32_t index = getThingIndex(thing); if (index == -1) { return RETURNVALUE_NOTPOSSIBLE; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return RETURNVALUE_NOTPOSSIBLE; } @@ -865,26 +896,26 @@ ReturnValue Tile::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t coun return RETURNVALUE_NOERROR; } -std::shared_ptr<Cylinder> Tile::queryDestination(int32_t &, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &tileFlags) { +std::shared_ptr<Cylinder> Tile::queryDestination(int32_t &, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &tileFlags) { std::shared_ptr<Tile> destTile = nullptr; - *destItem = nullptr; + destItem = nullptr; if (hasFlag(TILESTATE_FLOORCHANGE_DOWN)) { uint16_t dx = tilePos.x; uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z + 1; + const uint8_t dz = tilePos.z + 1; - std::shared_ptr<Tile> southDownTile = g_game().map.getTile(dx, dy - 1, dz); + const auto &southDownTile = g_game().map.getTile(dx, dy - 1, dz); if (southDownTile && southDownTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) { dy -= 2; destTile = g_game().map.getTile(dx, dy, dz); } else { - std::shared_ptr<Tile> eastDownTile = g_game().map.getTile(dx - 1, dy, dz); + const auto &eastDownTile = g_game().map.getTile(dx - 1, dy, dz); if (eastDownTile && eastDownTile->hasFlag(TILESTATE_FLOORCHANGE_EAST_ALT)) { dx -= 2; destTile = g_game().map.getTile(dx, dy, dz); } else { - std::shared_ptr<Tile> downTile = g_game().map.getTile(dx, dy, dz); + const auto &downTile = g_game().map.getTile(dx, dy, dz); if (downTile) { if (downTile->hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { ++dy; @@ -917,7 +948,7 @@ std::shared_ptr<Cylinder> Tile::queryDestination(int32_t &, const std::shared_pt } else if (hasFlag(TILESTATE_FLOORCHANGE)) { uint16_t dx = tilePos.x; uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z - 1; + const uint8_t dz = tilePos.z - 1; if (hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { --dy; @@ -953,14 +984,16 @@ std::shared_ptr<Cylinder> Tile::queryDestination(int32_t &, const std::shared_pt } if (destTile) { - std::shared_ptr<Thing> destThing = destTile->getTopDownItem(); + const auto &destThing = destTile->getTopDownItem(); if (destThing) { - *destItem = destThing->getItem(); - if (thing->getItem()) { - auto destCylinder = destThing->getCylinder(); - if (destCylinder && !destCylinder->getContainer()) { - return destThing->getCylinder(); - } + destItem = destThing->getItem(); + const auto &thingItem = thing ? thing->getItem() : nullptr; + if (!thingItem || thingItem->getMailbox() != destItem->getMailbox()) { + return destTile; + } + const auto &destCylinder = destThing->getCylinder(); + if (destCylinder && !destCylinder->getContainer()) { + return destThing->getCylinder(); } } } @@ -981,16 +1014,16 @@ std::vector<std::shared_ptr<Tile>> Tile::getSurroundingTiles() { }; } -void Tile::addThing(std::shared_ptr<Thing> thing) { +void Tile::addThing(const std::shared_ptr<Thing> &thing) { addThing(0, thing); } -void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { +void Tile::addThing(int32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { - return /*RETURNVALUE_NOTPOSSIBLE*/; + return; // RETURNVALUE_NOTPOSSIBLE } - std::shared_ptr<Creature> creature = thing->getCreature(); + const auto &creature = thing->getCreature(); if (creature) { Spectators::clearCache(); creature->setParent(static_self_cast<Tile>()); @@ -998,7 +1031,7 @@ void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); } else { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -1018,7 +1051,7 @@ void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { } else { const ItemType &oldType = Item::items[ground->getID()]; - std::shared_ptr<Item> oldGround = ground; + const auto &oldGround = ground; ground->resetParent(); ground = item; resetTileFlags(oldGround); @@ -1030,15 +1063,18 @@ void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { if (itemType.isSplash() && items) { // remove old splash if exists for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - std::shared_ptr<Item> oldSplash = *it; - if (!Item::items[oldSplash->getID()].isSplash()) { - continue; - } + // Need to increment the counter to avoid crash + const std::weak_ptr<Item> &weakSplash = *it; + if (const auto oldSplash = weakSplash.lock()) { + if (!Item::items[oldSplash->getID()].isSplash()) { + continue; + } - removeThing(oldSplash, 1); - oldSplash->resetParent(); - postRemoveNotification(oldSplash, nullptr, 0); - break; + postRemoveNotification(oldSplash, nullptr, 0); + removeThing(oldSplash, 1); + oldSplash->resetParent(); + break; + } } } @@ -1066,19 +1102,21 @@ void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { if (itemType.isMagicField()) { // remove old field item if exists if (items) { - for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - std::shared_ptr<MagicField> oldField = (*it)->getMagicField(); - if (oldField) { - if (oldField->isReplaceable()) { - removeThing(oldField, 1); - - oldField->resetParent(); - postRemoveNotification(oldField, nullptr, 0); - break; - } else { - // This magic field cannot be replaced. - item->resetParent(); - return; + for (auto it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { + std::weak_ptr<Item> weakField = *it; + if (const auto oldField = weakField.lock()) { + auto magicField = oldField->getMagicField(); + if (magicField) { + if (magicField->isReplaceable()) { + postRemoveNotification(magicField, nullptr, 0); + removeThing(magicField, 1); + magicField->resetParent(); + break; + } else { + // This magic field cannot be replaced. + item->resetParent(); + return; + } } } } @@ -1093,13 +1131,17 @@ void Tile::addThing(int32_t, std::shared_ptr<Thing> thing) { } } -void Tile::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) { - int32_t index = getThingIndex(thing); +void Tile::updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) { + if (!thing) { + return /*RETURNVALUE_NOTPOSSIBLE*/; + } + + const int32_t index = getThingIndex(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -1113,10 +1155,14 @@ void Tile::updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t c onUpdateTileItem(item, oldType, item, newType); } -void Tile::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { +void Tile::replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) { + if (!thing) { + return; + } + int32_t pos = index; - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } @@ -1136,7 +1182,7 @@ void Tile::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { TileItemVector* items = getItemList(); if (items && !isInserted) { - int32_t topItemSize = getTopItemCount(); + const int32_t topItemSize = getTopItemCount(); if (pos < topItemSize) { auto it = items->getBeginTopItem(); it += pos; @@ -1150,7 +1196,7 @@ void Tile::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { pos -= topItemSize; } - CreatureVector* creatures = getCreatures(); + const CreatureVector* creatures = getCreatures(); if (creatures) { if (!isInserted && pos < static_cast<int32_t>(creatures->size())) { return /*RETURNVALUE_NOTPOSSIBLE*/; @@ -1160,7 +1206,7 @@ void Tile::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { } if (items && !isInserted) { - int32_t downItemSize = getDownItemCount(); + const int32_t downItemSize = getDownItemCount(); if (pos < downItemSize) { auto it = items->getBeginDownItem() + pos; oldItem = *it; @@ -1184,12 +1230,16 @@ void Tile::replaceThing(uint32_t index, std::shared_ptr<Thing> thing) { } } -void Tile::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { - std::shared_ptr<Creature> creature = thing->getCreature(); +void Tile::removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) { + if (!thing) { + return; + } + + const auto &creature = thing->getCreature(); if (creature) { CreatureVector* creatures = getCreatures(); if (creatures) { - auto it = std::find(creatures->begin(), creatures->end(), thing); + const auto it = std::ranges::find(*creatures, thing); if (it != creatures->end()) { Spectators::clearCache(); creatures->erase(it); @@ -1198,12 +1248,12 @@ void Tile::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return; } - int32_t index = getThingIndex(item); + const int32_t index = getThingIndex(item); if (index == -1) { return; } @@ -1212,7 +1262,7 @@ void Tile::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { ground->resetParent(); ground = nullptr; - auto spectators = Spectators().find<Creature>(getPosition(), true); + const auto spectators = Spectators().find<Creature>(getPosition(), true); onRemoveTileItem(spectators.data(), std::vector<int32_t>(spectators.size(), 0), item); return; } @@ -1223,38 +1273,38 @@ void Tile::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { } if (item->isAlwaysOnTop()) { - auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); + const auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); if (it == items->getEndTopItem()) { return; } std::vector<int32_t> oldStackPosVector; - auto spectators = Spectators().find<Creature>(getPosition(), true); + const auto spectators = Spectators().find<Creature>(getPosition(), true); for (const auto &spectator : spectators) { if (const auto &tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item)); } } - item->resetParent(); items->erase(it); onRemoveTileItem(spectators.data(), oldStackPosVector, item); + item->resetParent(); } else { - auto it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item); + const auto it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item); if (it == items->getEndDownItem()) { return; } const ItemType &itemType = Item::items[item->getID()]; if (itemType.stackable && count != item->getItemCount()) { - uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, static_cast<int32_t>(item->getItemCount() - count))); + const uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, static_cast<int32_t>(item->getItemCount() - count))); item->setItemCount(newCount); onUpdateTileItem(item, itemType, item, itemType); } else { std::vector<int32_t> oldStackPosVector; - auto spectators = Spectators().find<Creature>(getPosition(), true); + const auto spectators = Spectators().find<Creature>(getPosition(), true); for (const auto &spectator : spectators) { if (const auto &tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfItem(spectator->getPlayer(), item)); @@ -1269,12 +1319,20 @@ void Tile::removeThing(std::shared_ptr<Thing> thing, uint32_t count) { } } -void Tile::removeCreature(std::shared_ptr<Creature> creature) { +void Tile::removeCreature(const std::shared_ptr<Creature> &creature) { + if (!creature) { + return; + } + g_game().map.getMapSector(tilePos.x, tilePos.y)->removeCreature(creature); removeThing(creature, 0); } -int32_t Tile::getThingIndex(std::shared_ptr<Thing> thing) const { +int32_t Tile::getThingIndex(const std::shared_ptr<Thing> &thing) const { + if (!thing) { + return -1; + } + int32_t n = -1; if (ground) { if (ground == thing) { @@ -1285,7 +1343,7 @@ int32_t Tile::getThingIndex(std::shared_ptr<Thing> thing) const { const TileItemVector* items = getItemList(); if (items) { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item && item->isAlwaysOnTop()) { for (auto it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { ++n; @@ -1300,7 +1358,7 @@ int32_t Tile::getThingIndex(std::shared_ptr<Thing> thing) const { if (const CreatureVector* creatures = getCreatures()) { if (thing->getCreature()) { - for (auto &creature : *creatures) { + for (const auto &creature : *creatures) { ++n; if (creature == thing) { return n; @@ -1312,7 +1370,7 @@ int32_t Tile::getThingIndex(std::shared_ptr<Thing> thing) const { } if (items) { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item && !item->isAlwaysOnTop()) { for (auto it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { ++n; @@ -1325,7 +1383,7 @@ int32_t Tile::getThingIndex(std::shared_ptr<Thing> thing) const { return -1; } -int32_t Tile::getClientIndexOfCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature) const { +int32_t Tile::getClientIndexOfCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature) const { int32_t n; if (ground) { n = 1; @@ -1339,10 +1397,10 @@ int32_t Tile::getClientIndexOfCreature(std::shared_ptr<Player> player, std::shar } if (const CreatureVector* creatures = getCreatures()) { - for (auto it = creatures->rbegin(); it != creatures->rend(); ++it) { - if (*it == creature) { + for (const auto &reverseCreature : std::ranges::reverse_view(*creatures)) { + if (reverseCreature == creature) { return n; - } else if (player->canSeeCreature(*it)) { + } else if (player->canSeeCreature(reverseCreature)) { ++n; } } @@ -1350,7 +1408,7 @@ int32_t Tile::getClientIndexOfCreature(std::shared_ptr<Player> player, std::shar return -1; } -int32_t Tile::getStackposOfCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature) const { +int32_t Tile::getStackposOfCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature) const { int32_t n; if (ground) { n = 1; @@ -1367,10 +1425,10 @@ int32_t Tile::getStackposOfCreature(std::shared_ptr<Player> player, std::shared_ } if (const CreatureVector* creatures = getCreatures()) { - for (auto it = creatures->rbegin(); it != creatures->rend(); ++it) { - if (*it == creature) { + for (const auto &reverseCreature : std::ranges::reverse_view(*creatures)) { + if (reverseCreature == creature) { return n; - } else if (player->canSeeCreature(*it)) { + } else if (player->canSeeCreature(reverseCreature)) { if (++n >= 10) { return -1; } @@ -1380,7 +1438,7 @@ int32_t Tile::getStackposOfCreature(std::shared_ptr<Player> player, std::shared_ return -1; } -int32_t Tile::getStackposOfItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item) const { +int32_t Tile::getStackposOfItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) const { int32_t n = 0; if (ground) { if (ground == item) { @@ -1408,7 +1466,7 @@ int32_t Tile::getStackposOfItem(std::shared_ptr<Player> player, std::shared_ptr< } if (const CreatureVector* creatures = getCreatures()) { - for (auto &creature : *creatures) { + for (const auto &creature : *creatures) { if (player->canSeeCreature(creature)) { if (++n >= 10) { return -1; @@ -1445,7 +1503,7 @@ uint32_t Tile::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const const TileItemVector* items = getItemList(); if (items) { - for (auto &item : *items) { + for (const auto &item : *items) { if (item->getID() == itemId) { count += Item::countByType(item, subType); } @@ -1465,7 +1523,7 @@ std::shared_ptr<Thing> Tile::getThing(size_t index) const { const TileItemVector* items = getItemList(); if (items) { - uint32_t topItemSize = items->getTopItemCount(); + const uint32_t topItemSize = items->getTopItemCount(); if (index < topItemSize) { return items->at(items->getDownItemCount() + index); } @@ -1485,13 +1543,17 @@ std::shared_ptr<Thing> Tile::getThing(size_t index) const { return nullptr; } -void Tile::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link /*= LINK_OWNER*/) { +void Tile::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link /*= LINK_OWNER*/) { + if (!thing) { + return; + } + for (const auto &spectator : Spectators().find<Player>(getPosition(), true)) { spectator->getPlayer()->postAddNotification(thing, oldParent, index, LINK_NEAR); } // add a reference to this item, it may be deleted after being added (mailbox for example) - std::shared_ptr<Creature> creature = thing->getCreature(); + const auto &creature = thing->getCreature(); std::shared_ptr<Item> item; if (creature) { item = nullptr; @@ -1501,17 +1563,17 @@ void Tile::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cyl if (link == LINK_OWNER) { if (hasFlag(TILESTATE_TELEPORT)) { - std::shared_ptr<Teleport> teleport = getTeleportItem(); + const auto &teleport = getTeleportItem(); if (teleport) { teleport->addThing(thing); } } else if (hasFlag(TILESTATE_TRASHHOLDER)) { - std::shared_ptr<TrashHolder> trashholder = getTrashHolder(); + const auto &trashholder = getTrashHolder(); if (trashholder) { trashholder->addThing(thing); } } else if (hasFlag(TILESTATE_MAILBOX)) { - std::shared_ptr<Mailbox> mailbox = getMailbox(); + const auto &mailbox = getMailbox(); if (mailbox) { mailbox->addThing(thing); } @@ -1526,7 +1588,11 @@ void Tile::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cyl } } -void Tile::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { +void Tile::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { + if (!thing) { + return; + } + auto spectators = Spectators().find<Player>(getPosition(), true); if (getThingCount() > 8) { @@ -1538,30 +1604,30 @@ void Tile::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr< } // calling movement scripts - std::shared_ptr<Creature> creature = thing->getCreature(); + const auto &creature = thing->getCreature(); if (creature) { g_moveEvents().onCreatureMove(creature, static_self_cast<Tile>(), MOVE_EVENT_STEP_OUT); } else { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item) { g_moveEvents().onItemMove(item, static_self_cast<Tile>(), false); } } } -void Tile::internalAddThing(std::shared_ptr<Thing> thing) { +void Tile::internalAddThing(const std::shared_ptr<Thing> &thing) { internalAddThing(0, thing); if (!thing || !thing->getParent()) { return; } - if (auto house = thing->getTile()->getHouse()) { - if (std::shared_ptr<Item> item = thing->getItem()) { + if (const auto &house = thing->getTile()->getHouse()) { + if (const auto &item = thing->getItem()) { if (item->getParent().get() != this) { return; } - std::shared_ptr<Door> door = item->getDoor(); + const auto &door = item->getDoor(); if (door && door->getDoorId() != 0) { house->addDoor(door); } @@ -1569,7 +1635,7 @@ void Tile::internalAddThing(std::shared_ptr<Thing> thing) { } } -void Tile::internalAddThing(uint32_t, std::shared_ptr<Thing> thing) { +void Tile::internalAddThing(uint32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { return; } @@ -1579,14 +1645,14 @@ void Tile::internalAddThing(uint32_t, std::shared_ptr<Thing> thing) { thing->setParent(getTile()); - std::shared_ptr<Creature> creature = thing->getCreature(); + const auto &creature = thing->getCreature(); if (creature) { Spectators::clearCache(); CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); } else { - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item == nullptr) { return; } @@ -1806,11 +1872,11 @@ bool Tile::isMovableBlocking() const { std::shared_ptr<Item> Tile::getUseItem(int32_t index) const { const TileItemVector* items = getItemList(); - if (!items || items->size() == 0) { + if (!items || items->empty()) { return ground; } - if (std::shared_ptr<Thing> thing = getThing(index)) { + if (const auto &thing = getThing(index)) { return thing->getItem(); } @@ -1819,12 +1885,12 @@ std::shared_ptr<Item> Tile::getUseItem(int32_t index) const { std::shared_ptr<Item> Tile::getDoorItem() const { const TileItemVector* items = getItemList(); - if (!items || items->size() == 0) { + if (!items || items->empty()) { return ground; } if (items) { - for (auto &item : *items) { + for (const auto &item : *items) { const ItemType &it = Item::items[item->getID()]; if (it.isDoor()) { return item; @@ -1835,7 +1901,11 @@ std::shared_ptr<Item> Tile::getDoorItem() const { return nullptr; } -void Tile::addZone(std::shared_ptr<Zone> zone) { +void Tile::addZone(const std::shared_ptr<Zone> &zone) { + if (!zone) { + return; + } + zones.emplace(zone); const auto &items = getItemList(); if (items) { @@ -1875,3 +1945,16 @@ void Tile::clearZones() { zones.erase(zone); } } + +void Tile::safeCall(std::function<void(void)> &&action) const { + if (g_dispatcher().context().isAsync()) { + g_dispatcher().addEvent([weak_self = std::weak_ptr<const SharedObject>(shared_from_this()), action = std::move(action)] { + if (weak_self.lock()) { + action(); + } + }, + g_dispatcher().context().getName()); + } else { + action(); + } +} diff --git a/src/items/tile.hpp b/src/items/tile.hpp index 1790cd2972a..a719f5dcef3 100644 --- a/src/items/tile.hpp +++ b/src/items/tile.hpp @@ -10,9 +10,6 @@ #pragma once #include "items/cylinder.hpp" -#include "declarations.hpp" -#include "items/item.hpp" -#include "utils/tools.hpp" class Creature; class Teleport; @@ -22,6 +19,9 @@ class MagicField; class BedItem; class House; class Zone; +class Cylinder; +class Item; +class ItemType; using CreatureVector = std::vector<std::shared_ptr<Creature>>; using ItemVector = std::vector<std::shared_ptr<Item>>; @@ -104,7 +104,7 @@ class Tile : public Cylinder, public SharedObject { static const std::shared_ptr<Tile> &nullptr_tile; Tile(uint16_t x, uint16_t y, uint8_t z) : tilePos(x, y, z) { } - virtual ~Tile() {}; + ~Tile() override = default; // non-copyable Tile(const Tile &) = delete; @@ -121,14 +121,14 @@ class Tile : public Cylinder, public SharedObject { return nullptr; } - int32_t getThrowRange() const override final { + int32_t getThrowRange() const final { return 0; } - bool isPushable() override final { + bool isPushable() final { return false; } - std::shared_ptr<Tile> getTile() override final { + std::shared_ptr<Tile> getTile() final { return static_self_cast<Tile>(); } @@ -144,13 +144,13 @@ class Tile : public Cylinder, public SharedObject { std::shared_ptr<Creature> getTopCreature() const; std::shared_ptr<Creature> getBottomCreature() const; - std::shared_ptr<Creature> getTopVisibleCreature(std::shared_ptr<Creature> creature) const; + std::shared_ptr<Creature> getTopVisibleCreature(const std::shared_ptr<Creature> &creature) const; - std::shared_ptr<Creature> getBottomVisibleCreature(std::shared_ptr<Creature> creature) const; + std::shared_ptr<Creature> getBottomVisibleCreature(const std::shared_ptr<Creature> &creature) const; std::shared_ptr<Item> getTopTopItem() const; std::shared_ptr<Item> getTopDownItem() const; bool isMovableBlocking() const; - std::shared_ptr<Thing> getTopVisibleThing(std::shared_ptr<Creature> creature); + std::shared_ptr<Thing> getTopVisibleThing(const std::shared_ptr<Creature> &creature); std::shared_ptr<Item> getItemByTopOrder(int32_t topOrder); size_t getThingCount() const { @@ -167,18 +167,16 @@ class Tile : public Cylinder, public SharedObject { uint32_t getDownItemCount() const; bool hasProperty(ItemProperty prop) const; - bool hasProperty(std::shared_ptr<Item> exclude, ItemProperty prop) const; + bool hasProperty(const std::shared_ptr<Item> &exclude, ItemProperty prop) const; - bool hasFlag(uint32_t flag) const { - return hasBitSet(flag, this->flags); - } + bool hasFlag(uint32_t flag) const; void setFlag(uint32_t flag) { this->flags |= flag; } void resetFlag(uint32_t flag) { this->flags &= ~flag; } - void addZone(std::shared_ptr<Zone> zone); + void addZone(const std::shared_ptr<Zone> &zone); void clearZones(); auto getZones() const { @@ -200,48 +198,48 @@ class Tile : public Cylinder, public SharedObject { bool hasHeight(uint32_t n) const; - std::string getDescription(int32_t lookDistance) override final; + std::string getDescription(int32_t lookDistance) final; - int32_t getClientIndexOfCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature) const; - int32_t getStackposOfCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature) const; - int32_t getStackposOfItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item) const; + int32_t getClientIndexOfCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature) const; + int32_t getStackposOfCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature) const; + int32_t getStackposOfItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) const; // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override final; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, std::shared_ptr<Creature> actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) final; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; std::vector<std::shared_ptr<Tile>> getSurroundingTiles(); - void addThing(std::shared_ptr<Thing> thing) override final; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; + void addThing(const std::shared_ptr<Thing> &thing) final; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; void updateTileFlags(const std::shared_ptr<Item> &item); - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override final; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override final; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) final; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) final; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override final; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) final; - void removeCreature(std::shared_ptr<Creature> creature); + void removeCreature(const std::shared_ptr<Creature> &creature); - int32_t getThingIndex(std::shared_ptr<Thing> thing) const override final; - size_t getFirstIndex() const override final; - size_t getLastIndex() const override final; - uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const override final; - std::shared_ptr<Thing> getThing(size_t index) const override final; + int32_t getThingIndex(const std::shared_ptr<Thing> &thing) const final; + size_t getFirstIndex() const final; + size_t getLastIndex() const final; + uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const final; + std::shared_ptr<Thing> getThing(size_t index) const final; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override final; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override final; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) final; - void internalAddThing(std::shared_ptr<Thing> thing) override; - void virtual internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void internalAddThing(const std::shared_ptr<Thing> &thing) override; + void internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; - const Position &getPosition() override final { + const Position &getPosition() final { return tilePos; } - bool isRemoved() override final { + bool isRemoved() final { return false; } @@ -261,10 +259,13 @@ class Tile : public Cylinder, public SharedObject { } } + // This method maintains safety in asynchronous calls, avoiding competition between threads. + void safeCall(std::function<void(void)> &&action) const; + private: - void onAddTileItem(std::shared_ptr<Item> item); - void onUpdateTileItem(std::shared_ptr<Item> oldItem, const ItemType &oldType, std::shared_ptr<Item> newItem, const ItemType &newType); - void onRemoveTileItem(const CreatureVector &spectators, const std::vector<int32_t> &oldStackPosVector, std::shared_ptr<Item> item); + void onAddTileItem(const std::shared_ptr<Item> &item); + void onUpdateTileItem(const std::shared_ptr<Item> &oldItem, const ItemType &oldType, const std::shared_ptr<Item> &newItem, const ItemType &newType); + void onRemoveTileItem(const CreatureVector &spectators, const std::vector<int32_t> &oldStackPosVector, const std::shared_ptr<Item> &item); void onUpdateTile(const CreatureVector &spectators); void setTileFlags(const std::shared_ptr<Item> &item); @@ -276,7 +277,7 @@ class Tile : public Cylinder, public SharedObject { std::shared_ptr<Item> ground = nullptr; Position tilePos; uint32_t flags = 0; - std::unordered_set<std::shared_ptr<Zone>> zones; + std::unordered_set<std::shared_ptr<Zone>> zones {}; }; // Used for walkable tiles, where there is high likeliness of @@ -287,6 +288,8 @@ class DynamicTile : public Tile { CreatureVector creatures; public: + explicit DynamicTile(const Position &position) : + Tile(position.x, position.y, position.z) { } DynamicTile(uint16_t x, uint16_t y, uint8_t z) : Tile(x, y, z) { } @@ -322,6 +325,8 @@ class StaticTile final : public Tile { std::unique_ptr<CreatureVector> creatures; public: + explicit StaticTile(const Position &position) : + Tile(position.x, position.y, position.z) { } StaticTile(uint16_t x, uint16_t y, uint8_t z) : Tile(x, y, z) { } diff --git a/src/items/trashholder.cpp b/src/items/trashholder.cpp index fe95557ce50..193d29b794e 100644 --- a/src/items/trashholder.cpp +++ b/src/items/trashholder.cpp @@ -8,10 +8,15 @@ */ #include "items/trashholder.hpp" + #include "game/game.hpp" -ReturnValue TrashHolder::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, std::shared_ptr<Creature> actor) { - std::shared_ptr<Item> item = thing->getItem(); +ReturnValue TrashHolder::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_t, uint32_t, const std::shared_ptr<Creature> &actor) { + if (!thing) { + return RETURNVALUE_NOERROR; + } + + const auto &item = thing->getItem(); if (item == nullptr) { return RETURNVALUE_NOERROR; } @@ -26,24 +31,24 @@ ReturnValue TrashHolder::queryMaxCount(int32_t, const std::shared_ptr<Thing> &, return RETURNVALUE_NOERROR; } -ReturnValue TrashHolder::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, std::shared_ptr<Creature> /*= nullptr*/) { +ReturnValue TrashHolder::queryRemove(const std::shared_ptr<Thing> &, uint32_t, uint32_t, const std::shared_ptr<Creature> & /*= nullptr */) { return RETURNVALUE_NOTPOSSIBLE; } -std::shared_ptr<Cylinder> TrashHolder::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item>*, uint32_t &) { +std::shared_ptr<Cylinder> TrashHolder::queryDestination(int32_t &, const std::shared_ptr<Thing> &, std::shared_ptr<Item> &, uint32_t &) { return static_self_cast<TrashHolder>(); } -void TrashHolder::addThing(std::shared_ptr<Thing> thing) { +void TrashHolder::addThing(const std::shared_ptr<Thing> &thing) { return addThing(0, thing); } -void TrashHolder::addThing(int32_t, std::shared_ptr<Thing> thing) { +void TrashHolder::addThing(int32_t, const std::shared_ptr<Thing> &thing) { if (!thing) { return; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (!item) { return; } @@ -54,7 +59,7 @@ void TrashHolder::addThing(int32_t, std::shared_ptr<Thing> thing) { const ItemType &it = Item::items[id]; if (item->isHangable() && it.isGroundTile()) { - std::shared_ptr<Tile> tile = std::dynamic_pointer_cast<Tile>(getParent()); + const std::shared_ptr<Tile> &tile = std::dynamic_pointer_cast<Tile>(getParent()); if (tile && tile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { return; } @@ -70,22 +75,22 @@ void TrashHolder::addThing(int32_t, std::shared_ptr<Thing> thing) { } } -void TrashHolder::updateThing(std::shared_ptr<Thing>, uint16_t, uint32_t) { +void TrashHolder::updateThing(const std::shared_ptr<Thing> &, uint16_t, uint32_t) { // } -void TrashHolder::replaceThing(uint32_t, std::shared_ptr<Thing>) { +void TrashHolder::replaceThing(uint32_t, const std::shared_ptr<Thing> &) { // } -void TrashHolder::removeThing(std::shared_ptr<Thing>, uint32_t) { +void TrashHolder::removeThing(const std::shared_ptr<Thing> &, uint32_t) { // } -void TrashHolder::postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t) { +void TrashHolder::postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t) { getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); } -void TrashHolder::postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t) { +void TrashHolder::postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t) { getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); } diff --git a/src/items/trashholder.hpp b/src/items/trashholder.hpp index 771c8687fbd..049260c57e0 100644 --- a/src/items/trashholder.hpp +++ b/src/items/trashholder.hpp @@ -21,24 +21,24 @@ class TrashHolder final : public Item, public Cylinder { return static_self_cast<TrashHolder>(); } - std::shared_ptr<Cylinder> getCylinder() override final { + std::shared_ptr<Cylinder> getCylinder() override { return getTrashHolder(); } // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; ReturnValue queryMaxCount(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) override; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; - void addThing(std::shared_ptr<Thing> thing) override; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; + void addThing(const std::shared_ptr<Thing> &thing) override; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; - void updateThing(std::shared_ptr<Thing> thing, uint16_t itemId, uint32_t count) override; - void replaceThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void updateThing(const std::shared_ptr<Thing> &thing, uint16_t itemId, uint32_t count) override; + void replaceThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; - void removeThing(std::shared_ptr<Thing> thing, uint32_t count) override; + void removeThing(const std::shared_ptr<Thing> &thing, uint32_t count) override; - void postAddNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; - void postRemoveNotification(std::shared_ptr<Thing> thing, std::shared_ptr<Cylinder> newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postAddNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &oldParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; + void postRemoveNotification(const std::shared_ptr<Thing> &thing, const std::shared_ptr<Cylinder> &newParent, int32_t index, CylinderLink_t link = LINK_OWNER) override; }; diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp index cce94603a60..2ec09945f36 100644 --- a/src/items/weapons/weapons.cpp +++ b/src/items/weapons/weapons.cpp @@ -7,22 +7,31 @@ * Website: https://docs.opentibiabr.com/ */ +#include "items/weapons/weapons.hpp" + +#include "config/configmanager.hpp" #include "creatures/combat/combat.hpp" #include "game/game.hpp" #include "lua/creature/events.hpp" -#include "items/weapons/weapons.hpp" - +#include "creatures/players/vocations/vocation.hpp" +#include "lib/di/container.hpp" +#include "lua/scripts/scripts.hpp" #include "lua/global/lua_variant.hpp" +#include "creatures/players/player.hpp" Weapons::Weapons() = default; Weapons::~Weapons() = default; -const WeaponShared_ptr Weapons::getWeapon(std::shared_ptr<Item> item) const { +Weapons &Weapons::getInstance() { + return inject<Weapons>(); +} + +WeaponShared_ptr Weapons::getWeapon(const std::shared_ptr<Item> &item) const { if (!item) { return nullptr; } - auto it = weapons.find(item->getID()); + const auto it = weapons.find(item->getID()); if (it == weapons.end()) { return nullptr; } @@ -52,7 +61,7 @@ void Weapons::clear(bool isFromXML /*= false*/) { weapons.clear(); } -bool Weapons::registerLuaEvent(WeaponShared_ptr event, bool fromXML /*= false*/) { +bool Weapons::registerLuaEvent(const WeaponShared_ptr &event, bool fromXML /*= false*/) { weapons[event->getID()] = event; if (fromXML) { event->setFromXML(fromXML); @@ -75,11 +84,40 @@ int32_t Weapons::getMaxWeaponDamage(uint32_t level, int32_t attackSkill, int32_t } } +Weapon::Weapon() = default; + +LuaScriptInterface* Weapon::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool Weapon::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t Weapon::getScriptId() const { + return m_scriptId; +} + +void Weapon::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool Weapon::isLoadedScriptId() const { + return m_scriptId != 0; +} + void Weapon::configureWeapon(const ItemType &it) { id = it.id; } -int32_t Weapon::playerWeaponCheck(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint8_t shootRange) const { +int32_t Weapon::playerWeaponCheck(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint8_t shootRange) const { const Position &playerPos = player->getPosition(); const Position &targetPos = target->getPosition(); if (playerPos.z != targetPos.z) { @@ -129,8 +167,8 @@ int32_t Weapon::playerWeaponCheck(std::shared_ptr<Player> player, std::shared_pt return 100; } -bool Weapon::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const { - int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); +bool Weapon::useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const { + const int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); if (damageModifier == 0) { return false; } @@ -139,22 +177,22 @@ bool Weapon::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> ite return true; } -CombatDamage Weapon::getCombatDamage(CombatDamage combat, std::shared_ptr<Player> player, std::shared_ptr<Item> item, int32_t damageModifier) const { +CombatDamage Weapon::getCombatDamage(CombatDamage combat, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, int32_t damageModifier) const { // Local variables - uint32_t level = player->getLevel(); - int16_t elementalAttack = getElementDamageValue(); - int32_t weaponAttack = std::max<int32_t>(0, item->getAttack()); - int32_t playerSkill = player->getWeaponSkill(item); - float attackFactor = player->getAttackFactor(); // full atk, balanced or full defense + const uint32_t level = player->getLevel(); + const int16_t elementalAttack = getElementDamageValue(); + const int32_t weaponAttack = std::max<int32_t>(0, item->getAttack()); + const int32_t playerSkill = player->getWeaponSkill(item); + const float attackFactor = player->getAttackFactor(); // full atk, balanced or full defense // Getting values factores - int32_t totalAttack = elementalAttack + weaponAttack; - double weaponAttackProportion = (double)weaponAttack / (double)totalAttack; + const int32_t totalAttack = elementalAttack + weaponAttack; + const double weaponAttackProportion = static_cast<double>(weaponAttack) / static_cast<double>(totalAttack); // Calculating damage - int32_t maxDamage = static_cast<int32_t>(Weapons::getMaxWeaponDamage(level, playerSkill, totalAttack, attackFactor, true) * player->getVocation()->meleeDamageMultiplier * damageModifier / 100); - int32_t minDamage = level / 5; - int32_t realDamage = normal_random(minDamage, maxDamage); + const int32_t maxDamage = static_cast<int32_t>(Weapons::getMaxWeaponDamage(level, playerSkill, totalAttack, attackFactor, true) * player->getVocation()->meleeDamageMultiplier * damageModifier / 100); + const int32_t minDamage = level / 5; + const int32_t realDamage = normal_random(minDamage, maxDamage); // Setting damage to combat combat.primary.value = realDamage * weaponAttackProportion; @@ -162,16 +200,16 @@ CombatDamage Weapon::getCombatDamage(CombatDamage combat, std::shared_ptr<Player return combat; } -bool Weapon::useFist(std::shared_ptr<Player> player, std::shared_ptr<Creature> target) { +bool Weapon::useFist(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target) { if (!Position::areInRange<1, 1>(player->getPosition(), target->getPosition())) { return false; } - float attackFactor = player->getAttackFactor(); - int32_t attackSkill = player->getSkillLevel(SKILL_FIST); - int32_t attackValue = 7; + const float attackFactor = player->getAttackFactor(); + const int32_t attackSkill = player->getSkillLevel(SKILL_FIST); + constexpr int32_t attackValue = 7; - int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor, true); + const int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor, true); CombatParams params; params.combatType = COMBAT_PHYSICALDAMAGE; @@ -192,7 +230,7 @@ bool Weapon::useFist(std::shared_ptr<Player> player, std::shared_ptr<Creature> t return true; } -void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target, int32_t damageModifier, int32_t cleavePercent) const { +void Weapon::internalUseWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target, int32_t damageModifier, int32_t cleavePercent) const { if (player) { if (params.soundCastEffect == SoundEffect_t::SILENCE) { g_game().sendDoubleSoundEffect(player->getPosition(), player->getHitSoundEffect(), player->getAttackSoundEffect(), player); @@ -201,7 +239,7 @@ void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<I } } - if (isLoadedCallback()) { + if (isLoadedScriptId()) { if (cleavePercent != 0) { return; } @@ -213,7 +251,7 @@ void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<I g_logger().debug("Weapon::internalUseWeapon - Lua callback executed."); } else { CombatDamage damage; - WeaponType_t weaponType = item->getWeaponType(); + const WeaponType_t weaponType = item->getWeaponType(); if (weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE || weaponType == WEAPON_MISSILE) { damage.origin = ORIGIN_RANGED; } else { @@ -256,8 +294,8 @@ void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<I onUsedWeapon(player, item, target->getTile()); } -void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Tile> tile) const { - if (isLoadedCallback()) { +void Weapon::internalUseWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &tile) const { + if (isLoadedScriptId()) { LuaVariant var; var.type = VARIANT_TARGETPOSITION; var.pos = tile->getPosition(); @@ -270,7 +308,7 @@ void Weapon::internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<I onUsedWeapon(player, item, tile); } -void Weapon::onUsedWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Tile> destTile) const { +void Weapon::onUsedWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &destTile) const { if (!player->hasFlag(PlayerFlags_t::NotGainSkill)) { skills_t skillType; uint32_t skillPoint; @@ -279,7 +317,7 @@ void Weapon::onUsedWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> } } - uint32_t manaCost = getManaCost(player); + const uint32_t manaCost = getManaCost(player); if (manaCost != 0) { player->addManaSpent(manaCost); player->changeMana(-static_cast<int32_t>(manaCost)); @@ -289,7 +327,7 @@ void Weapon::onUsedWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> } } - uint32_t healthCost = getHealthCost(player); + const uint32_t healthCost = getHealthCost(player); if (healthCost != 0) { player->changeHealth(-static_cast<int32_t>(healthCost)); } @@ -329,7 +367,7 @@ void Weapon::onUsedWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> } } -uint32_t Weapon::getManaCost(std::shared_ptr<Player> player) const { +uint32_t Weapon::getManaCost(const std::shared_ptr<Player> &player) const { if (mana != 0) { return mana; } @@ -341,7 +379,7 @@ uint32_t Weapon::getManaCost(std::shared_ptr<Player> player) const { return (player->getMaxMana() * manaPercent) / 100; } -int32_t Weapon::getHealthCost(std::shared_ptr<Player> player) const { +int32_t Weapon::getHealthCost(const std::shared_ptr<Player> &player) const { if (health != 0) { return health; } @@ -353,9 +391,9 @@ int32_t Weapon::getHealthCost(std::shared_ptr<Player> player) const { return (player->getMaxHealth() * healthPercent) / 100; } -bool Weapon::executeUseWeapon(std::shared_ptr<Player> player, const LuaVariant &var) const { +bool Weapon::executeUseWeapon(const std::shared_ptr<Player> &player, const LuaVariant &var) const { // onUseWeapon(player, var) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { std::string playerName = player ? player->getName() : "Player nullptr"; g_logger().error("[Weapon::executeUseWeapon - Player {} weaponId {}]" "Call stack overflow. Too many lua script calls being nested.", @@ -363,7 +401,7 @@ bool Weapon::executeUseWeapon(std::shared_ptr<Player> player, const LuaVariant & return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -371,13 +409,13 @@ bool Weapon::executeUseWeapon(std::shared_ptr<Player> player, const LuaVariant & getScriptInterface()->pushFunction(getScriptId()); LuaScriptInterface::pushUserdata<Player>(L, player); LuaScriptInterface::setMetatable(L, -1, "Player"); - getScriptInterface()->pushVariant(L, var); + LuaScriptInterface::pushVariant(L, var); return getScriptInterface()->callFunction(2); } -void Weapon::decrementItemCount(std::shared_ptr<Item> item) { - uint16_t count = item->getItemCount(); +void Weapon::decrementItemCount(const std::shared_ptr<Item> &item) { + const uint16_t count = item->getItemCount(); if (count > 1) { g_game().transformItem(item, item->getID(), count - 1); } else { @@ -386,7 +424,7 @@ void Weapon::decrementItemCount(std::shared_ptr<Item> item) { } bool Weapon::calculateSkillFormula(const std::shared_ptr<Player> &player, int32_t &attackSkill, int32_t &attackValue, float &attackFactor, int16_t &elementAttack, CombatDamage &damage, bool useCharges /* = false*/) const { - std::shared_ptr<Item> tool = player->getWeapon(); + const auto &tool = player->getWeapon(); if (!tool) { return false; } @@ -400,7 +438,7 @@ bool Weapon::calculateSkillFormula(const std::shared_ptr<Player> &player, int32_ } } - CombatType_t elementType = getElementType(); + const CombatType_t elementType = getElementType(); damage.secondary.type = elementType; bool shouldCalculateSecondaryDamage = false; @@ -411,7 +449,7 @@ bool Weapon::calculateSkillFormula(const std::shared_ptr<Player> &player, int32_ } if (useCharges) { - auto charges = tool->getAttribute<uint16_t>(ItemAttribute_t::CHARGES); + const auto charges = tool->getAttribute<uint16_t>(ItemAttribute_t::CHARGES); if (charges != 0) { g_game().transformItem(tool, tool->getID(), charges - 1); } @@ -422,8 +460,31 @@ bool Weapon::calculateSkillFormula(const std::shared_ptr<Player> &player, int32_ return shouldCalculateSecondaryDamage; } -WeaponMelee::WeaponMelee(LuaScriptInterface* interface) : - Weapon(interface) { +void Weapon::addVocWeaponMap(const std::string &vocName) { + const int32_t vocationId = g_vocations().getVocationId(vocName); + if (vocationId != -1) { + vocWeaponMap[vocationId] = true; + } +} + +std::shared_ptr<Combat> Weapon::getCombat() const { + if (!m_combat) { + g_logger().error("Weapon::getCombat() - m_combat is nullptr"); + return nullptr; + } + + return m_combat; +} + +std::shared_ptr<Combat> Weapon::getCombat() { + if (!m_combat) { + m_combat = std::make_shared<Combat>(); + } + + return m_combat; +} + +WeaponMelee::WeaponMelee() { // Add combat type and blocked attributes to the weapon params.blockedByArmor = true; params.blockedByShield = true; @@ -443,13 +504,13 @@ void WeaponMelee::configureWeapon(const ItemType &it) { Weapon::configureWeapon(it); } -bool WeaponMelee::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const { - int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); +bool WeaponMelee::useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const { + const int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); if (damageModifier == 0) { return false; } - int32_t cleavePercent = player->getCleavePercent(true); + const int32_t cleavePercent = player->getCleavePercent(true); if (cleavePercent > 0) { const Position &targetPos = target->getPosition(); const Position &playerPos = player->getPosition(); @@ -475,12 +536,12 @@ bool WeaponMelee::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item secondCleaveTargetPos.y++; } } - std::shared_ptr<Tile> firstTile = g_game().map.getTile(firstCleaveTargetPos.x, firstCleaveTargetPos.y, firstCleaveTargetPos.z); - std::shared_ptr<Tile> secondTile = g_game().map.getTile(secondCleaveTargetPos.x, secondCleaveTargetPos.y, secondCleaveTargetPos.z); + const auto &firstTile = g_game().map.getTile(firstCleaveTargetPos.x, firstCleaveTargetPos.y, firstCleaveTargetPos.z); + const auto &secondTile = g_game().map.getTile(secondCleaveTargetPos.x, secondCleaveTargetPos.y, secondCleaveTargetPos.z); if (firstTile) { - if (CreatureVector* tileCreatures = firstTile->getCreatures()) { - for (auto &tileCreature : *tileCreatures) { + if (const CreatureVector* tileCreatures = firstTile->getCreatures()) { + for (const auto &tileCreature : *tileCreatures) { if (tileCreature->getMonster() || (tileCreature->getPlayer() && !player->hasSecureMode())) { internalUseWeapon(player, item, tileCreature, damageModifier, cleavePercent); } @@ -488,8 +549,8 @@ bool WeaponMelee::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item } } if (secondTile) { - if (CreatureVector* tileCreatures = secondTile->getCreatures()) { - for (auto &tileCreature : *tileCreatures) { + if (const CreatureVector* tileCreatures = secondTile->getCreatures()) { + for (const auto &tileCreature : *tileCreatures) { if (tileCreature->getMonster() || (tileCreature->getPlayer() && !player->hasSecureMode())) { internalUseWeapon(player, item, tileCreature, damageModifier, cleavePercent); } @@ -503,14 +564,14 @@ bool WeaponMelee::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item return true; } -bool WeaponMelee::getSkillType(std::shared_ptr<Player> player, std::shared_ptr<Item> item, skills_t &skill, uint32_t &skillpoint) const { +bool WeaponMelee::getSkillType(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, skills_t &skill, uint32_t &skillpoint) const { if (player->getAddAttackSkill() && player->getLastAttackBlockType() != BLOCK_IMMUNITY) { skillpoint = 1; } else { skillpoint = 0; } - WeaponType_t weaponType = item->getWeaponType(); + const WeaponType_t weaponType = item->getWeaponType(); switch (weaponType) { case WEAPON_SWORD: { skill = SKILL_SWORD; @@ -533,18 +594,18 @@ bool WeaponMelee::getSkillType(std::shared_ptr<Player> player, std::shared_ptr<I return false; } -int32_t WeaponMelee::getElementDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature>, std::shared_ptr<Item> item) const { +int32_t WeaponMelee::getElementDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &, const std::shared_ptr<Item> &item) const { if (elementType == COMBAT_NONE) { return 0; } - int32_t attackSkill = player->getWeaponSkill(item); - int32_t attackValue = elementDamage; - float attackFactor = player->getAttackFactor(); - uint32_t level = player->getLevel(); + const int32_t attackSkill = player->getWeaponSkill(item); + const int32_t attackValue = elementDamage; + const float attackFactor = player->getAttackFactor(); + const uint32_t level = player->getLevel(); - int32_t maxValue = Weapons::getMaxWeaponDamage(level, attackSkill, attackValue, attackFactor, true); - int32_t minValue = level / 5; + const int32_t maxValue = Weapons::getMaxWeaponDamage(level, attackSkill, attackValue, attackFactor, true); + const int32_t minValue = level / 5; return -normal_random(minValue, static_cast<int32_t>(maxValue * player->getVocation()->meleeDamageMultiplier)); } @@ -553,16 +614,16 @@ int16_t WeaponMelee::getElementDamageValue() const { return elementDamage; } -int32_t WeaponMelee::getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature>, std::shared_ptr<Item> item, bool maxDamage /*= false*/) const { +int32_t WeaponMelee::getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &, const std::shared_ptr<Item> &item, bool maxDamage /*= false*/) const { using namespace std; - int32_t attackSkill = player->getWeaponSkill(item); - int32_t attackValue = std::max<int32_t>(0, item->getAttack()); - float attackFactor = player->getAttackFactor(); - uint32_t level = player->getLevel(); + const int32_t attackSkill = player->getWeaponSkill(item); + const int32_t attackValue = std::max<int32_t>(0, item->getAttack()); + const float attackFactor = player->getAttackFactor(); + const uint32_t level = player->getLevel(); - int32_t maxValue = static_cast<int32_t>(Weapons::getMaxWeaponDamage(level, attackSkill, attackValue, attackFactor, true) * player->getVocation()->meleeDamageMultiplier); + const int32_t maxValue = static_cast<int32_t>(Weapons::getMaxWeaponDamage(level, attackSkill, attackValue, attackFactor, true) * player->getVocation()->meleeDamageMultiplier); - int32_t minValue = level / 5; + const int32_t minValue = level / 5; if (maxDamage) { return -maxValue; @@ -571,8 +632,7 @@ int32_t WeaponMelee::getWeaponDamage(std::shared_ptr<Player> player, std::shared return -normal_random(minValue, (maxValue * static_cast<int32_t>(player->getVocation()->meleeDamageMultiplier))); } -WeaponDistance::WeaponDistance(LuaScriptInterface* interface) : - Weapon(interface) { +WeaponDistance::WeaponDistance() { // Add combat type and distance effect to the weapon params.blockedByArmor = true; params.combatType = COMBAT_PHYSICALDAMAGE; @@ -593,12 +653,12 @@ void WeaponDistance::configureWeapon(const ItemType &it) { Weapon::configureWeapon(it); } -bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const { +bool WeaponDistance::useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const { int32_t damageModifier; const ItemType &it = Item::items[id]; if (it.weaponType == WEAPON_AMMO) { - std::shared_ptr<Item> mainWeaponItem = player->getWeapon(true); - const WeaponShared_ptr mainWeapon = g_weapons().getWeapon(mainWeaponItem); + const auto &mainWeaponItem = player->getWeapon(true); + const WeaponShared_ptr &mainWeapon = g_weapons().getWeapon(mainWeaponItem); if (mainWeapon) { damageModifier = mainWeapon->playerWeaponCheck(player, target, mainWeaponItem->getShootRange()); } else { @@ -615,13 +675,13 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I bool perfectShot = false; const Position &playerPos = player->getPosition(); const Position &targetPos = target->getPosition(); - int32_t distanceX = Position::getDistanceX(targetPos, playerPos); - int32_t distanceY = Position::getDistanceY(targetPos, playerPos); + const int32_t distanceX = Position::getDistanceX(targetPos, playerPos); + const int32_t distanceY = Position::getDistanceY(targetPos, playerPos); int32_t damageX = player->getPerfectShotDamage(distanceX); int32_t damageY = player->getPerfectShotDamage(distanceY); if (it.weaponType == WEAPON_DISTANCE) { - std::shared_ptr<Item> quiver = player->getInventoryItem(CONST_SLOT_RIGHT); + const auto &quiver = player->getInventoryItem(CONST_SLOT_RIGHT); if (quiver && quiver->getWeaponType()) { if (quiver->getPerfectShotRange() == distanceX) { damageX -= quiver->getPerfectShotDamage(); @@ -637,8 +697,8 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I perfectShot = true; } else if (it.hitChance == 0) { // hit chance is based on distance to target and distance skill - uint32_t skill = player->getSkillLevel(SKILL_DISTANCE); - uint32_t distance = std::max<uint32_t>(distanceX, distanceY); + const uint32_t skill = player->getSkillLevel(SKILL_DISTANCE); + const uint32_t distance = std::max<uint32_t>(distanceX, distanceY); uint32_t maxHitChance; if (it.maxHitChance != -1) { @@ -734,7 +794,7 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I } if (!perfectShot && item->getWeaponType() == WEAPON_AMMO) { - std::shared_ptr<Item> bow = player->getWeapon(true); + const auto &bow = player->getWeapon(true); if (bow && bow->getHitChance() != 0) { chance += bow->getHitChance(); } @@ -744,7 +804,7 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I Weapon::internalUseWeapon(player, item, target, damageModifier); } else { // miss target - std::shared_ptr<Tile> destTile = target->getTile(); + auto destTile = target->getTile(); if (!Position::areInRange<1, 1, 0>(player->getPosition(), target->getPosition())) { static std::vector<std::pair<int32_t, int32_t>> destList { @@ -752,11 +812,11 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I }; std::ranges::shuffle(destList.begin(), destList.end(), getRandomGenerator()); - Position destPos = target->getPosition(); + const Position destPos = target->getPosition(); for (const auto &dir : destList) { // Blocking tiles or tiles without ground ain't valid targets for spears - auto tmpTile = g_game().map.getTile(static_cast<uint16_t>(destPos.x + dir.first), static_cast<uint16_t>(destPos.y + dir.second), destPos.z); + const auto &tmpTile = g_game().map.getTile(static_cast<uint16_t>(destPos.x + dir.first), static_cast<uint16_t>(destPos.y + dir.second), destPos.z); if (tmpTile && !tmpTile->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID) && tmpTile->getGround() != nullptr) { destTile = tmpTile; break; @@ -769,25 +829,25 @@ bool WeaponDistance::useWeapon(std::shared_ptr<Player> player, std::shared_ptr<I return true; } -int32_t WeaponDistance::getElementDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item) const { +int32_t WeaponDistance::getElementDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item) const { if (elementType == COMBAT_NONE) { return 0; } int32_t attackValue = elementDamage; - if (item->getWeaponType() == WEAPON_AMMO) { - std::shared_ptr<Item> weapon = player->getWeapon(true); + if (item && player && item->getWeaponType() == WEAPON_AMMO) { + const auto &weapon = player->getWeapon(true); if (weapon) { attackValue += item->getAttack(); attackValue += weapon->getAttack(); } } - int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); - float attackFactor = player->getAttackFactor(); + const int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); + const float attackFactor = player->getAttackFactor(); int32_t minValue = std::round(player->getLevel() / 5); - int32_t maxValue = std::round((0.09f * attackFactor) * attackSkill * attackValue + minValue) / 2; + const int32_t maxValue = std::round((0.09f * attackFactor) * attackSkill * attackValue + minValue) / 2; if (target) { if (target->getPlayer()) { @@ -804,12 +864,12 @@ int16_t WeaponDistance::getElementDamageValue() const { return elementDamage; } -int32_t WeaponDistance::getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, bool maxDamage /*= false*/) const { +int32_t WeaponDistance::getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, bool maxDamage /*= false*/) const { int32_t attackValue = item->getAttack(); bool hasElement = false; - if (item->getWeaponType() == WEAPON_AMMO) { - std::shared_ptr<Item> weapon = player->getWeapon(true); + if (player && item && item->getWeaponType() == WEAPON_AMMO) { + const auto &weapon = player->getWeapon(true); if (weapon) { const ItemType &it = Item::items[item->getID()]; if (it.abilities && it.abilities->elementDamage != 0) { @@ -821,8 +881,8 @@ int32_t WeaponDistance::getWeaponDamage(std::shared_ptr<Player> player, std::sha } } - int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); - float attackFactor = player->getAttackFactor(); + const int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); + const float attackFactor = player->getAttackFactor(); int32_t minValue = player->getLevel() / 5; int32_t maxValue = std::round((0.09f * attackFactor) * attackSkill * attackValue + minValue); @@ -830,7 +890,7 @@ int32_t WeaponDistance::getWeaponDamage(std::shared_ptr<Player> player, std::sha return -maxValue; } - if (target->getPlayer()) { + if (target && target->getPlayer()) { if (hasElement) { minValue /= 4; } else { @@ -846,10 +906,10 @@ int32_t WeaponDistance::getWeaponDamage(std::shared_ptr<Player> player, std::sha return -normal_random(minValue, (maxValue * static_cast<int32_t>(player->getVocation()->distDamageMultiplier))); } -bool WeaponDistance::getSkillType(std::shared_ptr<Player> player, std::shared_ptr<Item>, skills_t &skill, uint32_t &skillpoint) const { +bool WeaponDistance::getSkillType(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &, skills_t &skill, uint32_t &skillpoint) const { skill = SKILL_DISTANCE; - if (player->getAddAttackSkill()) { + if (player && player->getAddAttackSkill()) { switch (player->getLastAttackBlockType()) { case BLOCK_NONE: { skillpoint = 2; @@ -872,6 +932,8 @@ bool WeaponDistance::getSkillType(std::shared_ptr<Player> player, std::shared_pt return true; } +WeaponWand::WeaponWand() = default; + void WeaponWand::configureWeapon(const ItemType &it) { params.distanceEffect = it.shootType; const_cast<ItemType &>(it).combatType = params.combatType; @@ -879,36 +941,8 @@ void WeaponWand::configureWeapon(const ItemType &it) { Weapon::configureWeapon(it); } -int32_t WeaponWand::getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature>, std::shared_ptr<Item>, bool maxDamage /* = false*/) const { - if (!g_configManager().getBoolean(TOGGLE_CHAIN_SYSTEM)) { - // Returns maximum damage or a random value between minChange and maxChange - return maxDamage ? -maxChange : -normal_random(minChange, maxChange); - } - - // If chain system is enabled, calculates magic-based damage - int32_t attackSkill = 0; - int32_t attackValue = 0; - float attackFactor = 0.0; - [[maybe_unused]] int16_t elementAttack = 0; - [[maybe_unused]] CombatDamage combatDamage; - calculateSkillFormula(player, attackSkill, attackValue, attackFactor, elementAttack, combatDamage); - - auto magLevel = player->getMagicLevel(); - auto level = player->getLevel(); - - // Check if level is greater than zero before performing division - auto levelDivision = level > 0 ? level / 5.0 : 0.0; - - auto totalAttackValue = magLevel + attackValue; - - // Check if magLevel is greater than zero before performing division - auto magicLevelDivision = totalAttackValue > 0 ? totalAttackValue / 3.0 : 0.0; - - double min = levelDivision + magicLevelDivision; - double max = levelDivision + totalAttackValue; - - // Returns the calculated maximum damage or a random value between the calculated minimum and maximum - return maxDamage ? -max : -normal_random(min, max); +int32_t WeaponWand::getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &, const std::shared_ptr<Item> &, bool maxDamage /* = false*/) const { + return maxDamage ? -maxChange : -normal_random(minChange, maxChange); } int16_t WeaponWand::getElementDamageValue() const { diff --git a/src/items/weapons/weapons.hpp b/src/items/weapons/weapons.hpp index 59cc23636e2..dca7d814033 100644 --- a/src/items/weapons/weapons.hpp +++ b/src/items/weapons/weapons.hpp @@ -9,24 +9,29 @@ #pragma once -#include "lua/scripts/luascript.hpp" -#include "creatures/players/player.hpp" -#include "lua/scripts/scripts.hpp" -#include "creatures/combat/combat.hpp" #include "utils/utils_definitions.hpp" -#include "creatures/players/vocations/vocation.hpp" +#include "creatures/creatures_definitions.hpp" +#include "creatures/combat/combat.hpp" class Weapon; class WeaponMelee; class WeaponDistance; class WeaponWand; +class LuaScriptInterface; +class Combat; +class Player; +class Creature; +class Item; +class ItemType; +class Vocation; +class Tile; struct LuaVariant; using WeaponUnique_ptr = std::unique_ptr<Weapon>; using WeaponShared_ptr = std::shared_ptr<Weapon>; -class Weapons final : public Scripts { +class Weapons { public: Weapons(); ~Weapons(); @@ -35,16 +40,14 @@ class Weapons final : public Scripts { Weapons(const Weapons &) = delete; Weapons &operator=(const Weapons &) = delete; - static Weapons &getInstance() { - return inject<Weapons>(); - } + static Weapons &getInstance(); - const WeaponShared_ptr getWeapon(std::shared_ptr<Item> item) const; + WeaponShared_ptr getWeapon(const std::shared_ptr<Item> &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(WeaponShared_ptr event, bool fromXML = false); + bool registerLuaEvent(const WeaponShared_ptr &event, bool fromXML = false); void clear(bool isFromXML = false); private: @@ -53,24 +56,23 @@ class Weapons final : public Scripts { constexpr auto g_weapons = Weapons::getInstance; -class Weapon : public Script { +class Weapon { public: - using Script::Script; - + Weapon(); virtual void configureWeapon(const ItemType &it); virtual bool interruptSwing() const { return false; } - int32_t playerWeaponCheck(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint8_t shootRange) const; - static bool useFist(std::shared_ptr<Player> player, std::shared_ptr<Creature> target); - virtual bool useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const; + int32_t playerWeaponCheck(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint8_t shootRange) const; + static bool useFist(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target); + virtual bool useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const; - virtual int32_t getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, bool maxDamage = false) const = 0; - virtual int32_t getElementDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item) const = 0; + virtual int32_t getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, bool maxDamage = false) const = 0; + virtual int32_t getElementDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item) const = 0; virtual CombatType_t getElementType() const = 0; virtual int16_t getElementDamageValue() const = 0; - virtual CombatDamage getCombatDamage(CombatDamage combat, std::shared_ptr<Player> player, std::shared_ptr<Item> item, int32_t damageModifier) const; + virtual CombatDamage getCombatDamage(CombatDamage combat, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, int32_t damageModifier) const; uint16_t getID() const { return id; } @@ -162,12 +164,7 @@ class Weapon : public Script { wieldInfo |= info; } - void addVocWeaponMap(std::string vocName) { - int32_t vocationId = g_vocations().getVocationId(vocName); - if (vocationId != -1) { - vocWeaponMap[vocationId] = true; - } - } + void addVocWeaponMap(const std::string &vocName); const std::string &getVocationString() const { return vocationString; @@ -204,37 +201,32 @@ class Weapon : public Script { return weaponType; } - std::shared_ptr<Combat> getCombat() const { - if (!m_combat) { - g_logger().error("Weapon::getCombat() - m_combat is nullptr"); - return nullptr; - } + std::shared_ptr<Combat> getCombat() const; - return m_combat; - } - - std::shared_ptr<Combat> getCombat() { - if (!m_combat) { - m_combat = std::make_shared<Combat>(); - } - - return m_combat; - } + std::shared_ptr<Combat> getCombat(); bool calculateSkillFormula(const std::shared_ptr<Player> &player, int32_t &attackSkill, int32_t &attackValue, float &attackFactor, int16_t &elementAttack, CombatDamage &damage, bool useCharges = false) const; + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; + protected: - void internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target, int32_t damageModifier, int32_t cleavePercent = 0) const; - void internalUseWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Tile> tile) const; + void internalUseWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target, int32_t damageModifier, int32_t cleavePercent = 0) const; + void internalUseWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &tile) const; private: - virtual bool getSkillType(std::shared_ptr<Player>, std::shared_ptr<Item>, skills_t &, uint32_t &) const { + int32_t m_scriptId {}; + + virtual bool getSkillType(const std::shared_ptr<Player> &, const std::shared_ptr<Item> &, skills_t &, uint32_t &) const { return false; } - uint32_t getManaCost(std::shared_ptr<Player> player) const; - int32_t getHealthCost(std::shared_ptr<Player> player) const; - bool executeUseWeapon(std::shared_ptr<Player> player, const LuaVariant &var) const; + uint32_t getManaCost(const std::shared_ptr<Player> &player) const; + int32_t getHealthCost(const std::shared_ptr<Player> &player) const; + bool executeUseWeapon(const std::shared_ptr<Player> &player, const LuaVariant &var) const; uint16_t id = 0; @@ -252,11 +244,11 @@ class Weapon : public Script { bool premium = false; bool wieldUnproperly = false; bool m_isDisabledChain = false; - std::string vocationString = ""; + std::string vocationString; - void onUsedWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Tile> destTile) const; + void onUsedWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Tile> &destTile) const; - static void decrementItemCount(std::shared_ptr<Item> item); + static void decrementItemCount(const std::shared_ptr<Item> &item); WeaponAction_t action = WEAPONACTION_NONE; CombatParams params; @@ -276,70 +268,58 @@ class Weapon : public Script { class WeaponMelee final : public Weapon { public: - explicit WeaponMelee(LuaScriptInterface* interface); - - std::string getScriptTypeName() const override { - return "onUseWeapon"; - } + explicit WeaponMelee(); void configureWeapon(const ItemType &it) override; - bool useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const override; + bool useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const override; - int32_t getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, bool maxDamage = false) const override; - int32_t getElementDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item) const override; + int32_t getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, bool maxDamage = false) const override; + int32_t getElementDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item) const override; CombatType_t getElementType() const override { return elementType; } virtual int16_t getElementDamageValue() const override; private: - bool getSkillType(std::shared_ptr<Player> player, std::shared_ptr<Item> item, skills_t &skill, uint32_t &skillpoint) const override; + bool getSkillType(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, skills_t &skill, uint32_t &skillpoint) const override; uint16_t elementDamage = 0; CombatType_t elementType = COMBAT_NONE; }; class WeaponDistance final : public Weapon { public: - explicit WeaponDistance(LuaScriptInterface* interface); - - std::string getScriptTypeName() const override { - return "onUseWeapon"; - } + explicit WeaponDistance(); void configureWeapon(const ItemType &it) override; bool interruptSwing() const override { return true; } - bool useWeapon(std::shared_ptr<Player> player, std::shared_ptr<Item> item, std::shared_ptr<Creature> target) const override; + bool useWeapon(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::shared_ptr<Creature> &target) const override; - int32_t getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, bool maxDamage = false) const override; - int32_t getElementDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item) const override; + int32_t getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, bool maxDamage = false) const override; + int32_t getElementDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item) const override; CombatType_t getElementType() const override { return elementType; } virtual int16_t getElementDamageValue() const override; private: - bool getSkillType(std::shared_ptr<Player> player, std::shared_ptr<Item> item, skills_t &skill, uint32_t &skillpoint) const override; + bool getSkillType(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, skills_t &skill, uint32_t &skillpoint) const override; CombatType_t elementType = COMBAT_NONE; uint16_t elementDamage = 0; }; -class WeaponWand final : public Weapon { +class WeaponWand : public Weapon { public: - using Weapon::Weapon; - - std::string getScriptTypeName() const override { - return "onUseWeapon"; - } + explicit WeaponWand(); void configureWeapon(const ItemType &it) override; - int32_t getWeaponDamage(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, bool maxDamage = false) const override; - int32_t getElementDamage(std::shared_ptr<Player>, std::shared_ptr<Creature>, std::shared_ptr<Item>) const override { + int32_t getWeaponDamage(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, bool maxDamage = false) const override; + int32_t getElementDamage(const std::shared_ptr<Player> &, const std::shared_ptr<Creature> &, const std::shared_ptr<Item> &) const override { return 0; } CombatType_t getElementType() const override { @@ -355,7 +335,7 @@ class WeaponWand final : public Weapon { } private: - bool getSkillType(std::shared_ptr<Player>, std::shared_ptr<Item>, skills_t &, uint32_t &) const override { + bool getSkillType(const std::shared_ptr<Player> &, const std::shared_ptr<Item> &, skills_t &, uint32_t &) const override { return false; } diff --git a/src/kv/kv.cpp b/src/kv/kv.cpp index 0a7cfe6827d..95b19ca8590 100644 --- a/src/kv/kv.cpp +++ b/src/kv/kv.cpp @@ -21,12 +21,12 @@ KVStore &KVStore::getInstance() { } void KVStore::set(const std::string &key, const std::initializer_list<ValueWrapper> &init_list) { - ValueWrapper wrappedInitList(init_list); + const ValueWrapper wrappedInitList(init_list); set(key, wrappedInitList); } void KVStore::set(const std::string &key, const std::initializer_list<std::pair<const std::string, ValueWrapper>> &init_list) { - ValueWrapper wrappedInitList(init_list); + const ValueWrapper wrappedInitList(init_list); set(key, wrappedInitList); } @@ -37,7 +37,7 @@ void KVStore::set(const std::string &key, const ValueWrapper &value) { void KVStore::setLocked(const std::string &key, const ValueWrapper &value) { logger.trace("KVStore::set({})", key); - auto it = store_.find(key); + const auto it = store_.find(key); if (it != store_.end()) { it->second.first = value; lruQueue_.splice(lruQueue_.begin(), lruQueue_, it->second.second); diff --git a/src/kv/kv.hpp b/src/kv/kv.hpp index c00a0fd4204..eefc97d83c5 100644 --- a/src/kv/kv.hpp +++ b/src/kv/kv.hpp @@ -18,12 +18,14 @@ #include <unordered_set> #include <iomanip> #include <list> + #include <utility> #endif #include "kv/value_wrapper.hpp" class KV : public std::enable_shared_from_this<KV> { public: + virtual ~KV() = default; virtual void set(const std::string &key, const std::initializer_list<ValueWrapper> &init_list) = 0; virtual void set(const std::string &key, const std::initializer_list<std::pair<const std::string, ValueWrapper>> &init_list) = 0; virtual void set(const std::string &key, const ValueWrapper &value) = 0; @@ -47,8 +49,8 @@ class KV : public std::enable_shared_from_this<KV> { static std::string generateUUID() { std::lock_guard<std::mutex> lock(mutex_); - auto now = std::chrono::system_clock::now().time_since_epoch(); - auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now).count(); + const auto now = std::chrono::system_clock::now().time_since_epoch(); + const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now).count(); if (milliseconds != lastTimestamp_) { counter_ = 0; @@ -90,8 +92,8 @@ class KVStore : public KV { store_.clear(); } - std::shared_ptr<KV> scoped(const std::string &scope) override final; - std::unordered_set<std::string> keys(const std::string &prefix = ""); + std::shared_ptr<KV> scoped(const std::string &scope) final; + std::unordered_set<std::string> keys(const std::string &prefix = "") override; protected: phmap::parallel_flat_hash_map<std::string, std::pair<ValueWrapper, std::list<std::string>::iterator>> getStore() { @@ -120,8 +122,8 @@ class KVStore : public KV { class ScopedKV final : public KV { public: - ScopedKV(Logger &logger, KVStore &rootKV, const std::string &prefix) : - logger(logger), rootKV_(rootKV), prefix_(prefix) { } + ScopedKV(Logger &logger, KVStore &rootKV, std::string prefix) : + logger(logger), rootKV_(rootKV), prefix_(std::move(prefix)) { } void set(const std::string &key, const std::initializer_list<ValueWrapper> &init_list) override { rootKV_.set(buildKey(key), init_list); @@ -139,7 +141,7 @@ class ScopedKV final : public KV { template <typename T> T get(const std::string &key, bool forceLoad = false) { - auto optValue = get(key, forceLoad); + const auto optValue = get(key, forceLoad); if (optValue.has_value()) { return optValue->get<T>(); } @@ -150,7 +152,7 @@ class ScopedKV final : public KV { return rootKV_.saveAll(); } - std::shared_ptr<KV> scoped(const std::string &scope) override final { + std::shared_ptr<KV> scoped(const std::string &scope) override { logger.trace("ScopedKV::scoped({})", buildKey(scope)); return std::make_shared<ScopedKV>(logger, rootKV_, buildKey(scope)); } diff --git a/src/kv/kv_sql.cpp b/src/kv/kv_sql.cpp index 18f3c7a3205..0f353048854 100644 --- a/src/kv/kv_sql.cpp +++ b/src/kv/kv_sql.cpp @@ -19,20 +19,20 @@ KVSQL::KVSQL(Database &db, Logger &logger) : KVStore(logger), db(db) { } std::optional<ValueWrapper> KVSQL::load(const std::string &key) { - auto query = fmt::format("SELECT `key_name`, `timestamp`, `value` FROM `kv_store` WHERE `key_name` = {}", db.escapeString(key)); - auto result = db.storeQuery(query); + const auto query = fmt::format("SELECT `key_name`, `timestamp`, `value` FROM `kv_store` WHERE `key_name` = {}", db.escapeString(key)); + const auto result = db.storeQuery(query); if (result == nullptr) { return std::nullopt; } unsigned long size; - auto data = result->getStream("value", size); + const auto data = result->getStream("value", size); if (data == nullptr) { return std::nullopt; } ValueWrapper valueWrapper; - auto timestamp = result->getNumber<uint64_t>("timestamp"); + const auto timestamp = result->getNumber<uint64_t>("timestamp"); Canary::protobuf::kv::ValueWrapper protoValue; if (protoValue.ParseFromArray(data, static_cast<int>(size))) { valueWrapper = ProtoSerializable::fromProto(protoValue, timestamp); @@ -45,8 +45,8 @@ std::optional<ValueWrapper> KVSQL::load(const std::string &key) { std::vector<std::string> KVSQL::loadPrefix(const std::string &prefix /* = ""*/) { std::vector<std::string> keys; std::string keySearch = db.escapeString(prefix + "%"); - auto query = fmt::format("SELECT `key_name` FROM `kv_store` WHERE `key_name` LIKE {}", keySearch); - auto result = db.storeQuery(query); + const auto query = fmt::format("SELECT `key_name` FROM `kv_store` WHERE `key_name` LIKE {}", keySearch); + const auto result = db.storeQuery(query); if (result == nullptr) { return keys; } @@ -66,14 +66,14 @@ bool KVSQL::save(const std::string &key, const ValueWrapper &value) { return update.execute(); } -bool KVSQL::prepareSave(const std::string &key, const ValueWrapper &value, DBInsert &update) { - auto protoValue = ProtoSerializable::toProto(value); +bool KVSQL::prepareSave(const std::string &key, const ValueWrapper &value, DBInsert &update) const { + const auto protoValue = ProtoSerializable::toProto(value); std::string data; if (!protoValue.SerializeToString(&data)) { return false; } if (value.isDeleted()) { - auto query = fmt::format("DELETE FROM `kv_store` WHERE `key_name` = {}", db.escapeString(key)); + const auto query = fmt::format("DELETE FROM `kv_store` WHERE `key_name` = {}", db.escapeString(key)); return db.executeQuery(query); } @@ -83,7 +83,7 @@ bool KVSQL::prepareSave(const std::string &key, const ValueWrapper &value, DBIns bool KVSQL::saveAll() { auto store = getStore(); - bool success = DBTransaction::executeWithinTransaction([this, &store]() { + const bool success = DBTransaction::executeWithinTransaction([this, &store]() { auto update = dbUpdate(); if (!std::ranges::all_of(store, [this, &update](const auto &kv) { const auto &[key, value] = kv; diff --git a/src/kv/kv_sql.hpp b/src/kv/kv_sql.hpp index 43bedada82f..f58f9cc4751 100644 --- a/src/kv/kv_sql.hpp +++ b/src/kv/kv_sql.hpp @@ -26,7 +26,7 @@ class KVSQL final : public KVStore { std::vector<std::string> loadPrefix(const std::string &prefix = "") override; std::optional<ValueWrapper> load(const std::string &key) override; bool save(const std::string &key, const ValueWrapper &value) override; - bool prepareSave(const std::string &key, const ValueWrapper &value, DBInsert &update); + bool prepareSave(const std::string &key, const ValueWrapper &value, DBInsert &update) const; DBInsert dbUpdate(); diff --git a/src/kv/value_wrapper.cpp b/src/kv/value_wrapper.cpp index 72920b6972a..69fb942bab4 100644 --- a/src/kv/value_wrapper.cpp +++ b/src/kv/value_wrapper.cpp @@ -8,13 +8,14 @@ */ #include "kv/value_wrapper.hpp" + #include "utils/tools.hpp" ValueWrapper::ValueWrapper(uint64_t timestamp) : timestamp_(timestamp == 0 ? getTimeMsNow() : timestamp) { } -ValueWrapper::ValueWrapper(const ValueVariant &value, uint64_t timestamp) : - data_(value), timestamp_(timestamp == 0 ? getTimeMsNow() : timestamp) { } +ValueWrapper::ValueWrapper(ValueVariant value, uint64_t timestamp) : + data_(std::move(value)), timestamp_(timestamp == 0 ? getTimeMsNow() : timestamp) { } ValueWrapper::ValueWrapper(const std::string &value, uint64_t timestamp) : data_(value), timestamp_(timestamp == 0 ? getTimeMsNow() : timestamp) { } @@ -37,7 +38,7 @@ ValueWrapper::ValueWrapper(const std::initializer_list<std::pair<const std::stri timestamp_(timestamp == 0 ? getTimeMsNow() : timestamp) { } std::optional<ValueWrapper> ValueWrapper::get(const std::string &key) const { - auto pval = std::get_if<MapType>(&data_); + const auto pval = std::get_if<MapType>(&data_); if (!pval) { return std::nullopt; } @@ -55,7 +56,7 @@ std::optional<ValueWrapper> ValueWrapper::get(const std::string &key) const { } std::optional<ValueWrapper> ValueWrapper::get(size_t index) const { - if (auto pval = std::get_if<ArrayType>(&data_)) { + if (const auto pval = std::get_if<ArrayType>(&data_)) { if (index < pval->size()) { return (*pval)[index]; } diff --git a/src/kv/value_wrapper.hpp b/src/kv/value_wrapper.hpp index df1ad85e8df..4bb844dcb97 100644 --- a/src/kv/value_wrapper.hpp +++ b/src/kv/value_wrapper.hpp @@ -24,7 +24,7 @@ class ValueWrapper { public: explicit ValueWrapper(uint64_t timestamp = 0); - explicit(false) ValueWrapper(const ValueVariant &value, uint64_t timestamp = 0); + explicit(false) ValueWrapper(ValueVariant value, uint64_t timestamp = 0); explicit(false) ValueWrapper(const std::string &value, uint64_t timestamp = 0); explicit(false) ValueWrapper(bool value, uint64_t timestamp = 0); explicit(false) ValueWrapper(int value, uint64_t timestamp = 0); diff --git a/src/kv/value_wrapper_proto.cpp b/src/kv/value_wrapper_proto.cpp index e4d60bed354..2235c56e19d 100644 --- a/src/kv/value_wrapper_proto.cpp +++ b/src/kv/value_wrapper_proto.cpp @@ -31,14 +31,14 @@ namespace ProtoHelpers { } void setProtoArrayValue(Canary::protobuf::kv::ValueWrapper &protoValue, const ArrayType &arg) { - auto arrayValue = protoValue.mutable_array_value(); + const auto arrayValue = protoValue.mutable_array_value(); for (const auto &elem : arg) { *arrayValue->add_values() = ProtoSerializable::toProto(elem); } } void setProtoMapValue(Canary::protobuf::kv::ValueWrapper &protoValue, const MapType &arg) { - auto mapValue = protoValue.mutable_map_value(); + const auto mapValue = protoValue.mutable_map_value(); for (const auto &[key, value] : arg) { auto* elem = mapValue->add_items(); elem->set_key(key); diff --git a/src/kv/value_wrapper_proto.hpp b/src/kv/value_wrapper_proto.hpp index 382b91a040b..9d5a61865ab 100644 --- a/src/kv/value_wrapper_proto.hpp +++ b/src/kv/value_wrapper_proto.hpp @@ -21,13 +21,9 @@ using MapType = phmap::flat_hash_map<std::string, std::shared_ptr<ValueWrapper>> using ValueVariant = std::variant<StringType, BooleanType, IntType, DoubleType, ArrayType, MapType>; // Forward declaration for protobuf class -namespace Canary { - namespace protobuf { - namespace kv { - class ValueWrapper; - } // namespace kv - } // namespace protobuf -} // namespace Canary +namespace Canary::protobuf::kv { + class ValueWrapper; +} struct ProtoSerializable { static Canary::protobuf::kv::ValueWrapper toProto(const ValueWrapper &obj); diff --git a/src/lib/di/runtime_provider.hpp b/src/lib/di/runtime_provider.hpp index 1c9292b5e73..70fad336e97 100644 --- a/src/lib/di/runtime_provider.hpp +++ b/src/lib/di/runtime_provider.hpp @@ -44,9 +44,9 @@ namespace extension { template <class T, class TInitialization, class TMemory, class... TArgs> auto get(const TInitialization &, const TMemory &, TArgs &&... args) const { - auto it = bindings_.find(std::type_index(typeid(T))); + const auto it = bindings_.find(std::type_index(typeid(T))); if (it == bindings_.end()) { - return get<T>(std::integral_constant < bool, !std::is_abstract<T>::value && std::is_constructible<T, TArgs...>::value > {}, std::forward<TArgs>(args)...); + return get<T>(std::integral_constant < bool, !std::is_abstract_v<T> && std::is_constructible_v<T, TArgs...> > {}, std::forward<TArgs>(args)...); } return static_cast<T*>(it->second()); } @@ -121,19 +121,19 @@ namespace extension { core::injector<runtime_provider<TErrorPolicy, TScopeTraits>> { core::init {} } { } template <class T> - /*non explicit*/ injector(const T &bindings) : + /*non explicit*/ explicit injector(const T &bindings) : injector() { install(bindings); } - template <class T, std::enable_if_t<!std::is_base_of<core::injector_base, T>::value, int> = 0> + template <class T, std::enable_if_t<!std::is_base_of_v<core::injector_base, T>, int> = 0> void install(const T &binding) { this->cfg().bindings()[std::type_index(typeid(typename T::expected))] = [this, binding] { return make<typename T::given>(binding); }; } - template <class T, std::enable_if_t<std::is_base_of<core::injector_base, T>::value, int> = 0> + template <class T, std::enable_if_t<std::is_base_of_v<core::injector_base, T>, int> = 0> void install(const T &injector) { install(typename T::deps {}, injector, aux::identity<typename T::config> {}); } diff --git a/src/lib/di/shared.hpp b/src/lib/di/shared.hpp index c1e2f0c6743..f57257d7abd 100644 --- a/src/lib/di/shared.hpp +++ b/src/lib/di/shared.hpp @@ -28,7 +28,7 @@ namespace extension { #if !defined(BOOST_DI_NOT_THREAD_SAFE) //<<lock mutex so that move will be synchronized>> - explicit scope(scope &&other) noexcept : + scope(scope &&other) noexcept : scope(std::move(other), std::scoped_lock<std::mutex>(other.mutex_)) { } //<<synchronized move constructor>> scope(scope &&other, const std::scoped_lock<std::mutex> &) noexcept : diff --git a/src/lib/di/soft_singleton.cpp b/src/lib/di/soft_singleton.cpp index 8fb90288cee..8a2add1c026 100644 --- a/src/lib/di/soft_singleton.cpp +++ b/src/lib/di/soft_singleton.cpp @@ -7,6 +7,7 @@ * Website: https://docs.opentibiabr.com/ */ #include "lib/di/soft_singleton.hpp" + #include "utils/tools.hpp" SoftSingleton::SoftSingleton(std::string id) : diff --git a/src/lib/di/soft_singleton.hpp b/src/lib/di/soft_singleton.hpp index b64df1c77b6..99ef85fe9c9 100644 --- a/src/lib/di/soft_singleton.hpp +++ b/src/lib/di/soft_singleton.hpp @@ -6,9 +6,8 @@ * Contributors: https://github.com/opentibiabr/canary/graphs/contributors * Website: https://docs.opentibiabr.com/ */ -#pragma once -#include <iostream> +#pragma once class SoftSingleton { public: diff --git a/src/lib/metrics/metrics.cpp b/src/lib/metrics/metrics.cpp index cf11060125a..a6fa18063aa 100644 --- a/src/lib/metrics/metrics.cpp +++ b/src/lib/metrics/metrics.cpp @@ -8,7 +8,8 @@ * Website: https://docs.opentibiabr.com/ */ - #include "metrics.hpp" + #include "lib/metrics/metrics.hpp" + #include "lib/di/container.hpp" using namespace metrics; diff --git a/src/lib/metrics/metrics.hpp b/src/lib/metrics/metrics.hpp index 2a6a1e5838f..428398f7c00 100644 --- a/src/lib/metrics/metrics.hpp +++ b/src/lib/metrics/metrics.hpp @@ -171,7 +171,7 @@ class ScopedLatency { 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<double> &histogram, [[maybe_unused]] const std::map<std::string, std::string> &attrs = {}, [[maybe_unused]] const std::string &context = std::string()) {}; - void stop() {}; + void stop() const {}; ~ScopedLatency() = default; }; @@ -203,17 +203,17 @@ namespace metrics { Metrics() = default; ~Metrics() = default; - void init([[maybe_unused]] Options opts) {}; - void initHistograms() {}; - void shutdown() {}; + void init([[maybe_unused]] Options opts) const {}; + void initHistograms() const {}; + void shutdown() const {}; static Metrics &getInstance() { return inject<Metrics>(); }; - void addCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] double value, [[maybe_unused]] const std::map<std::string, std::string> &attrs = {}) { } + void addCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] double value, [[maybe_unused]] const std::map<std::string, std::string> &attrs = {}) const { } - void addUpDownCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] int value, [[maybe_unused]] const std::map<std::string, std::string> &attrs = {}) { } + void addUpDownCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] int value, [[maybe_unused]] const std::map<std::string, std::string> &attrs = {}) const { } friend class ScopedLatency; }; diff --git a/src/lib/thread/thread_pool.cpp b/src/lib/thread/thread_pool.cpp index d67fd63b7d9..0d6b6f5be43 100644 --- a/src/lib/thread/thread_pool.cpp +++ b/src/lib/thread/thread_pool.cpp @@ -28,7 +28,7 @@ ThreadPool::ThreadPool(Logger &logger) : start(); } -void ThreadPool::start() { +void ThreadPool::start() const { logger.info("Running with {} threads.", get_thread_count()); } diff --git a/src/lib/thread/thread_pool.hpp b/src/lib/thread/thread_pool.hpp index 69084090308..ecdaaab40e1 100644 --- a/src/lib/thread/thread_pool.hpp +++ b/src/lib/thread/thread_pool.hpp @@ -19,7 +19,7 @@ class ThreadPool : public BS::thread_pool { ThreadPool(const ThreadPool &) = delete; ThreadPool &operator=(const ThreadPool &) = delete; - void start(); + void start() const; void shutdown(); static int16_t getThreadId() { diff --git a/src/lua/callbacks/callbacks_definitions.hpp b/src/lua/callbacks/callbacks_definitions.hpp index 6c19cc809c9..faea6b2d1e2 100644 --- a/src/lua/callbacks/callbacks_definitions.hpp +++ b/src/lua/callbacks/callbacks_definitions.hpp @@ -23,7 +23,6 @@ enum class EventCallback_t : uint16_t { creatureOnChangeOutfit, creatureOnAreaCombat, creatureOnTargetCombat, - creatureOnHear, creatureOnDrainHealth, creatureOnCombat, // Party @@ -62,9 +61,6 @@ enum class EventCallback_t : uint16_t { // Monster monsterOnDropLoot, monsterPostDropLoot, - monsterOnSpawn, - // Npc - npcOnSpawn, // Zone zoneBeforeCreatureEnter, zoneBeforeCreatureLeave, diff --git a/src/lua/callbacks/creaturecallback.cpp b/src/lua/callbacks/creaturecallback.cpp index 11e33a9b1e1..6f279f46d98 100644 --- a/src/lua/callbacks/creaturecallback.cpp +++ b/src/lua/callbacks/creaturecallback.cpp @@ -9,13 +9,16 @@ #include "lua/callbacks/creaturecallback.hpp" +#include "creatures/creature.hpp" +#include "lua/scripts/luascript.hpp" + bool CreatureCallback::startScriptInterface(int32_t scriptId) { if (scriptId == -1) { return false; } - if (!scriptInterface->reserveScriptEnv()) { - auto targetCreature = m_targetCreature.lock(); + if (!LuaScriptInterface::reserveScriptEnv()) { + const auto targetCreature = m_targetCreature.lock(); g_logger().error( "[CreatureCallback::startScriptInterface] - {} {} Call stack overflow. Too many lua script calls being nested.", getCreatureClass(targetCreature), @@ -24,8 +27,7 @@ bool CreatureCallback::startScriptInterface(int32_t scriptId) { return false; } - scriptInterface - ->getScriptEnv() + LuaScriptInterface::getScriptEnv() ->setScriptId(scriptId, scriptInterface); L = scriptInterface->getLuaState(); @@ -35,12 +37,12 @@ bool CreatureCallback::startScriptInterface(int32_t scriptId) { return true; } -void CreatureCallback::pushSpecificCreature(std::shared_ptr<Creature> creature) { - if (std::shared_ptr<Npc> npc = creature->getNpc()) { +void CreatureCallback::pushSpecificCreature(const std::shared_ptr<Creature> &creature) { + if (const auto &npc = creature->getNpc()) { LuaScriptInterface::pushUserdata<Npc>(L, npc); - } else if (std::shared_ptr<Monster> monster = creature->getMonster()) { + } else if (const auto &monster = creature->getMonster()) { LuaScriptInterface::pushUserdata<Monster>(L, monster); - } else if (std::shared_ptr<Player> player = creature->getPlayer()) { + } else if (const auto &player = creature->getPlayer()) { LuaScriptInterface::pushUserdata<Player>(L, player); } else { return; @@ -50,7 +52,37 @@ void CreatureCallback::pushSpecificCreature(std::shared_ptr<Creature> creature) LuaScriptInterface::setMetatable(L, -1, getCreatureClass(creature)); } -std::string CreatureCallback::getCreatureClass(std::shared_ptr<Creature> creature) { +bool CreatureCallback::persistLuaState() const { + return params > 0 && scriptInterface->callFunction(params); +} + +void CreatureCallback::pushCreature(const std::shared_ptr<Creature> &creature) { + params++; + LuaScriptInterface::pushUserdata<Creature>(L, creature); + LuaScriptInterface::setCreatureMetatable(L, -1, creature); +} + +void CreatureCallback::pushPosition(const Position &position, int32_t stackpos) { + params++; + LuaScriptInterface::pushPosition(L, position, stackpos); +} + +void CreatureCallback::pushNumber(int32_t number) { + params++; + lua_pushnumber(L, number); +} + +void CreatureCallback::pushString(const std::string &str) { + params++; + LuaScriptInterface::pushString(L, str); +} + +void CreatureCallback::pushBoolean(const bool str) { + params++; + LuaScriptInterface::pushBoolean(L, str); +} + +std::string CreatureCallback::getCreatureClass(const std::shared_ptr<Creature> &creature) { if (!creature) { return ""; } diff --git a/src/lua/callbacks/creaturecallback.hpp b/src/lua/callbacks/creaturecallback.hpp index f7665720410..6922b43a87c 100644 --- a/src/lua/callbacks/creaturecallback.hpp +++ b/src/lua/callbacks/creaturecallback.hpp @@ -9,52 +9,35 @@ #pragma once -#include "creatures/creature.hpp" - class Creature; +class LuaScriptInterface; + +struct Position; class CreatureCallback { public: - CreatureCallback(LuaScriptInterface* scriptInterface, std::shared_ptr<Creature> targetCreature) : + CreatureCallback(LuaScriptInterface* scriptInterface, const std::shared_ptr<Creature> &targetCreature) : scriptInterface(scriptInterface), m_targetCreature(targetCreature) {}; - ~CreatureCallback() { } + ~CreatureCallback() = default; bool startScriptInterface(int32_t scriptId); - void pushSpecificCreature(std::shared_ptr<Creature> creature); + void pushSpecificCreature(const std::shared_ptr<Creature> &creature); - bool persistLuaState() { - return params > 0 && scriptInterface->callFunction(params); - } + bool persistLuaState() const; - void pushCreature(std::shared_ptr<Creature> creature) { - params++; - LuaScriptInterface::pushUserdata<Creature>(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } + void pushCreature(const std::shared_ptr<Creature> &creature); - void pushPosition(const Position &position, int32_t stackpos = 0) { - params++; - LuaScriptInterface::pushPosition(L, position, stackpos); - } + void pushPosition(const Position &position, int32_t stackpos = 0); - void pushNumber(int32_t number) { - params++; - lua_pushnumber(L, number); - } + void pushNumber(int32_t number); - void pushString(const std::string &str) { - params++; - LuaScriptInterface::pushString(L, str); - } + void pushString(const std::string &str); - void pushBoolean(const bool str) { - params++; - LuaScriptInterface::pushBoolean(L, str); - } + void pushBoolean(const bool str); protected: - static std::string getCreatureClass(std::shared_ptr<Creature> creature); + static std::string getCreatureClass(const std::shared_ptr<Creature> &creature); private: LuaScriptInterface* scriptInterface; diff --git a/src/lua/callbacks/event_callback.cpp b/src/lua/callbacks/event_callback.cpp index 6591755d18f..16e0aa182d0 100644 --- a/src/lua/callbacks/event_callback.cpp +++ b/src/lua/callbacks/event_callback.cpp @@ -9,10 +9,12 @@ #include "lua/callbacks/event_callback.hpp" -#include "utils/tools.hpp" -#include "items/item.hpp" +#include "creatures/players/grouping/party.hpp" #include "creatures/players/player.hpp" #include "game/zones/zone.hpp" +#include "items/containers/container.hpp" +#include "items/item.hpp" +#include "lua/scripts/scripts.hpp" /** * @class EventCallback @@ -23,26 +25,52 @@ * * @see Script */ -EventCallback::EventCallback(LuaScriptInterface* scriptInterface, const std::string &callbackName, bool skipDuplicationCheck) : - Script(scriptInterface), m_callbackName(callbackName), m_skipDuplicationCheck(skipDuplicationCheck) { -} +EventCallback::EventCallback(const std::string &callbackName, bool skipDuplicationCheck) : + m_callbackName(callbackName), m_skipDuplicationCheck(skipDuplicationCheck) { } -std::string EventCallback::getName() const { - return m_callbackName; +LuaScriptInterface* EventCallback::getScriptInterface() const { + return &g_scripts().getScriptInterface(); } -bool EventCallback::skipDuplicationCheck() const { - return m_skipDuplicationCheck; +bool EventCallback::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[EventCallback::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; } std::string EventCallback::getScriptTypeName() const { return m_scriptTypeName; } -void EventCallback::setScriptTypeName(const std::string_view newName) { +void EventCallback::setScriptTypeName(std::string_view newName) { m_scriptTypeName = newName; } +int32_t EventCallback::getScriptId() const { + return m_scriptId; +} + +void EventCallback::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool EventCallback::isLoadedScriptId() const { + return m_scriptId != 0; +} + +std::string EventCallback::getName() const { + return m_callbackName; +} + +bool EventCallback::skipDuplicationCheck() const { + return m_skipDuplicationCheck; +} + EventCallback_t EventCallback::getType() const { return m_callbackType; } @@ -53,15 +81,15 @@ void EventCallback::setType(EventCallback_t type) { // Lua functions // Creature -bool EventCallback::creatureOnChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::creatureOnChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::creatureOnChangeOutfit - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -75,8 +103,8 @@ bool EventCallback::creatureOnChangeOutfit(std::shared_ptr<Creature> creature, c return getScriptInterface()->callFunction(2); } -ReturnValue EventCallback::creatureOnAreaCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Tile> tile, bool aggressive) const { - if (!getScriptInterface()->reserveScriptEnv()) { +ReturnValue EventCallback::creatureOnAreaCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile, bool aggressive) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::creatureOnAreaCombat - " "Creature {} on tile position {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -84,7 +112,7 @@ ReturnValue EventCallback::creatureOnAreaCombat(std::shared_ptr<Creature> creatu return RETURNVALUE_NOTPOSSIBLE; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -103,7 +131,7 @@ ReturnValue EventCallback::creatureOnAreaCombat(std::shared_ptr<Creature> creatu LuaScriptInterface::pushBoolean(L, aggressive); ReturnValue returnValue; - if (getScriptInterface()->protectedCall(L, 3, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 3, 1) != 0) { returnValue = RETURNVALUE_NOTPOSSIBLE; LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { @@ -111,12 +139,12 @@ ReturnValue EventCallback::creatureOnAreaCombat(std::shared_ptr<Creature> creatu lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return returnValue; } -ReturnValue EventCallback::creatureOnTargetCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target) const { - if (!getScriptInterface()->reserveScriptEnv()) { +ReturnValue EventCallback::creatureOnTargetCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::creatureOnTargetCombat - " "Creature {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -124,7 +152,7 @@ ReturnValue EventCallback::creatureOnTargetCombat(std::shared_ptr<Creature> crea return RETURNVALUE_NOTPOSSIBLE; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -141,7 +169,7 @@ ReturnValue EventCallback::creatureOnTargetCombat(std::shared_ptr<Creature> crea LuaScriptInterface::setCreatureMetatable(L, -1, target); ReturnValue returnValue; - if (getScriptInterface()->protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { returnValue = RETURNVALUE_NOTPOSSIBLE; LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { @@ -149,39 +177,12 @@ ReturnValue EventCallback::creatureOnTargetCombat(std::shared_ptr<Creature> crea lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return returnValue; } -void EventCallback::creatureOnHear(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> speaker, const std::string &words, SpeakClasses type) const { - if (!getScriptInterface()->reserveScriptEnv()) { - g_logger().error("[EventCallback::creatureOnHear - " - "Creature {} speaker {}] " - "Call stack overflow. Too many lua script calls being nested.", - creature->getName(), speaker->getName()); - return; - } - - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); - scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); - - lua_State* L = getScriptInterface()->getLuaState(); - getScriptInterface()->pushFunction(getScriptId()); - - LuaScriptInterface::pushUserdata<Creature>(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushUserdata<Creature>(L, speaker); - LuaScriptInterface::setCreatureMetatable(L, -1, speaker); - - LuaScriptInterface::pushString(L, words); - lua_pushnumber(L, type); - - getScriptInterface()->callVoidFunction(4); -} - -void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::creatureOnDrainHealth(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::creatureOnDrainHealth - " "Creature {} attacker {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -189,7 +190,7 @@ void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, st return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -216,7 +217,7 @@ void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, st lua_pushnumber(L, colorPrimary); lua_pushnumber(L, colorSecondary); - if (getScriptInterface()->protectedCall(L, 8, 6) != 0) { + if (LuaScriptInterface::protectedCall(L, 8, 6) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { typePrimary = LuaScriptInterface::getNumber<CombatType_t>(L, -6); @@ -228,7 +229,7 @@ void EventCallback::creatureOnDrainHealth(std::shared_ptr<Creature> creature, st lua_pop(L, 6); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } void EventCallback::creatureOnCombat(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) const { @@ -284,8 +285,8 @@ void EventCallback::creatureOnCombat(std::shared_ptr<Creature> attacker, std::sh } // Party -bool EventCallback::partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::partyOnJoin(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::partyOnJoin - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -293,7 +294,7 @@ bool EventCallback::partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Pl return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -308,8 +309,8 @@ bool EventCallback::partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Pl return getScriptInterface()->callFunction(2); } -bool EventCallback::partyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::partyOnLeave(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::partyOnLeave - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -317,7 +318,7 @@ bool EventCallback::partyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<P return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -332,15 +333,15 @@ bool EventCallback::partyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<P return getScriptInterface()->callFunction(2); } -bool EventCallback::partyOnDisband(std::shared_ptr<Party> party) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::partyOnDisband(const std::shared_ptr<Party> &party) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::partyOnDisband - Party leader {}] Call stack " "overflow. Too many lua script calls being nested.", party->getLeader() ? party->getLeader()->getName() : "unknown"); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -352,13 +353,13 @@ bool EventCallback::partyOnDisband(std::shared_ptr<Party> party) const { return getScriptInterface()->callFunction(1); } -void EventCallback::partyOnShareExperience(std::shared_ptr<Party> party, uint64_t &exp) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::partyOnShareExperience(const std::shared_ptr<Party> &party, uint64_t &exp) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("Party leader {}. Call stack overflow. Too many lua script calls being nested.", party->getLeader() ? party->getLeader()->getName() : "unknown"); return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -369,19 +370,19 @@ void EventCallback::partyOnShareExperience(std::shared_ptr<Party> party, uint64_ lua_pushnumber(L, exp); - if (getScriptInterface()->protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } // Player -bool EventCallback::playerOnBrowseField(std::shared_ptr<Player> player, const Position &position) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnBrowseField(const std::shared_ptr<Player> &player, const Position &position) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnBrowseField - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -389,7 +390,7 @@ bool EventCallback::playerOnBrowseField(std::shared_ptr<Player> player, const Po return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -403,8 +404,8 @@ bool EventCallback::playerOnBrowseField(std::shared_ptr<Player> player, const Po return getScriptInterface()->callFunction(2); } -void EventCallback::playerOnLook(std::shared_ptr<Player> player, const Position &position, std::shared_ptr<Thing> thing, uint8_t stackpos, int32_t lookDistance) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnLook(const std::shared_ptr<Player> &player, const Position &position, const std::shared_ptr<Thing> &thing, uint8_t stackpos, int32_t lookDistance) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnLook - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -412,7 +413,7 @@ void EventCallback::playerOnLook(std::shared_ptr<Player> player, const Position return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -421,10 +422,10 @@ void EventCallback::playerOnLook(std::shared_ptr<Player> player, const Position LuaScriptInterface::pushUserdata<Player>(L, player); LuaScriptInterface::setMetatable(L, -1, "Player"); - if (std::shared_ptr<Creature> creature = thing->getCreature()) { + if (const auto &creature = thing->getCreature()) { LuaScriptInterface::pushUserdata<Creature>(L, creature); LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else if (std::shared_ptr<Item> item = thing->getItem()) { + } else if (const auto &item = thing->getItem()) { LuaScriptInterface::pushUserdata<Item>(L, item); LuaScriptInterface::setItemMetatable(L, -1, item); } else { @@ -437,8 +438,8 @@ void EventCallback::playerOnLook(std::shared_ptr<Player> player, const Position getScriptInterface()->callVoidFunction(4); } -void EventCallback::playerOnLookInBattleList(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, int32_t lookDistance) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnLookInBattleList(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, int32_t lookDistance) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnLookInBattleList - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -446,7 +447,7 @@ void EventCallback::playerOnLookInBattleList(std::shared_ptr<Player> player, std return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -463,8 +464,8 @@ void EventCallback::playerOnLookInBattleList(std::shared_ptr<Player> player, std getScriptInterface()->callVoidFunction(3); } -void EventCallback::playerOnLookInTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> partner, std::shared_ptr<Item> item, int32_t lookDistance) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnLookInTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &partner, const std::shared_ptr<Item> &item, int32_t lookDistance) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnLookInTrade - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -472,7 +473,7 @@ void EventCallback::playerOnLookInTrade(std::shared_ptr<Player> player, std::sha return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -492,8 +493,8 @@ void EventCallback::playerOnLookInTrade(std::shared_ptr<Player> player, std::sha getScriptInterface()->callVoidFunction(4); } -bool EventCallback::playerOnLookInShop(std::shared_ptr<Player> player, const ItemType* itemType, uint8_t count) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnLookInShop(const std::shared_ptr<Player> &player, const ItemType* itemType, uint8_t count) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnLookInShop - " "Player {} itemType {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -501,7 +502,7 @@ bool EventCallback::playerOnLookInShop(std::shared_ptr<Player> player, const Ite return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -518,8 +519,8 @@ bool EventCallback::playerOnLookInShop(std::shared_ptr<Player> player, const Ite return getScriptInterface()->callFunction(3); } -void EventCallback::playerOnRemoveCount(std::shared_ptr<Player> player, std::shared_ptr<Item> item) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnRemoveCount(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnMove - " "Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -527,7 +528,7 @@ void EventCallback::playerOnRemoveCount(std::shared_ptr<Player> player, std::sha return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -542,20 +543,20 @@ void EventCallback::playerOnRemoveCount(std::shared_ptr<Player> player, std::sha getScriptInterface()->callFunction(2); } -bool EventCallback::playerOnMoveItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPos, const Position &toPos, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) const { +bool EventCallback::playerOnMoveItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPos, const Position &toPos, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) const { if (!getScriptInterface()) { g_logger().error("script interface nullptr"); return false; } - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Action::executeUse - Player {}, on item {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), item->getName()); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -577,8 +578,8 @@ bool EventCallback::playerOnMoveItem(std::shared_ptr<Player> player, std::shared return getScriptInterface()->callFunction(7); } -void EventCallback::playerOnItemMoved(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnItemMoved(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnItemMoved - " "Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -586,7 +587,7 @@ void EventCallback::playerOnItemMoved(std::shared_ptr<Player> player, std::share return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -608,8 +609,8 @@ void EventCallback::playerOnItemMoved(std::shared_ptr<Player> player, std::share getScriptInterface()->callVoidFunction(7); } -void EventCallback::playerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t zone) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnChangeZone(const std::shared_ptr<Player> &player, ZoneType_t zone) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnChangeZone - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -617,7 +618,7 @@ void EventCallback::playerOnChangeZone(std::shared_ptr<Player> player, ZoneType_ return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -630,8 +631,8 @@ void EventCallback::playerOnChangeZone(std::shared_ptr<Player> player, ZoneType_ getScriptInterface()->callVoidFunction(2); } -bool EventCallback::playerOnMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, const Position &fromPosition, const Position &toPosition) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnMoveCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, const Position &fromPosition, const Position &toPosition) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnMoveCreature - " "Player {} creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -639,7 +640,7 @@ bool EventCallback::playerOnMoveCreature(std::shared_ptr<Player> player, std::sh return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -657,8 +658,8 @@ bool EventCallback::playerOnMoveCreature(std::shared_ptr<Player> player, std::sh return getScriptInterface()->callFunction(4); } -void EventCallback::playerOnReportRuleViolation(std::shared_ptr<Player> player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnReportRuleViolation(const std::shared_ptr<Player> &player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnReportRuleViolation - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -666,7 +667,7 @@ void EventCallback::playerOnReportRuleViolation(std::shared_ptr<Player> player, return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -686,8 +687,8 @@ void EventCallback::playerOnReportRuleViolation(std::shared_ptr<Player> player, getScriptInterface()->callVoidFunction(6); } -void EventCallback::playerOnReportBug(std::shared_ptr<Player> player, const std::string &message, const Position &position, uint8_t category) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnReportBug(const std::shared_ptr<Player> &player, const std::string &message, const Position &position, uint8_t category) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnReportBug - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -695,7 +696,7 @@ void EventCallback::playerOnReportBug(std::shared_ptr<Player> player, const std: return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -711,8 +712,8 @@ void EventCallback::playerOnReportBug(std::shared_ptr<Player> player, const std: getScriptInterface()->callFunction(4); } -bool EventCallback::playerOnTurn(std::shared_ptr<Player> player, Direction direction) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnTurn(const std::shared_ptr<Player> &player, Direction direction) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnTurn - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -720,7 +721,7 @@ bool EventCallback::playerOnTurn(std::shared_ptr<Player> player, Direction direc return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -734,8 +735,8 @@ bool EventCallback::playerOnTurn(std::shared_ptr<Player> player, Direction direc return getScriptInterface()->callFunction(2); } -bool EventCallback::playerOnTradeRequest(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnTradeRequest(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnTradeRequest - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -743,7 +744,7 @@ bool EventCallback::playerOnTradeRequest(std::shared_ptr<Player> player, std::sh return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -761,8 +762,8 @@ bool EventCallback::playerOnTradeRequest(std::shared_ptr<Player> player, std::sh return getScriptInterface()->callFunction(3); } -bool EventCallback::playerOnTradeAccept(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item, std::shared_ptr<Item> targetItem) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnTradeAccept(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &targetItem) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnTradeAccept - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -770,7 +771,7 @@ bool EventCallback::playerOnTradeAccept(std::shared_ptr<Player> player, std::sha return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -791,8 +792,8 @@ bool EventCallback::playerOnTradeAccept(std::shared_ptr<Player> player, std::sha return getScriptInterface()->callFunction(4); } -void EventCallback::playerOnGainExperience(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint64_t &exp, uint64_t rawExp) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnGainExperience(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint64_t &exp, uint64_t rawExp) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnGainExperience - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -800,7 +801,7 @@ void EventCallback::playerOnGainExperience(std::shared_ptr<Player> player, std:: return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -819,18 +820,18 @@ void EventCallback::playerOnGainExperience(std::shared_ptr<Player> player, std:: lua_pushnumber(L, exp); lua_pushnumber(L, rawExp); - if (getScriptInterface()->protectedCall(L, 4, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 4, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void EventCallback::playerOnLoseExperience(std::shared_ptr<Player> player, uint64_t &exp) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnLoseExperience(const std::shared_ptr<Player> &player, uint64_t &exp) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnLoseExperience - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -838,7 +839,7 @@ void EventCallback::playerOnLoseExperience(std::shared_ptr<Player> player, uint6 return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -849,18 +850,18 @@ void EventCallback::playerOnLoseExperience(std::shared_ptr<Player> player, uint6 lua_pushnumber(L, exp); - if (getScriptInterface()->protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void EventCallback::playerOnGainSkillTries(std::shared_ptr<Player> player, skills_t skill, uint64_t &tries) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnGainSkillTries(const std::shared_ptr<Player> &player, skills_t skill, uint64_t &tries) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnGainSkillTries - " "Player {} skill {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -868,7 +869,7 @@ void EventCallback::playerOnGainSkillTries(std::shared_ptr<Player> player, skill return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -880,18 +881,18 @@ void EventCallback::playerOnGainSkillTries(std::shared_ptr<Player> player, skill lua_pushnumber(L, skill); lua_pushnumber(L, tries); - if (getScriptInterface()->protectedCall(L, 3, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 3, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { tries = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void EventCallback::playerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnCombat(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, CombatDamage &damage) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnCombat - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -899,7 +900,7 @@ void EventCallback::playerOnCombat(std::shared_ptr<Player> player, std::shared_p return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -924,7 +925,7 @@ void EventCallback::playerOnCombat(std::shared_ptr<Player> player, std::shared_p LuaScriptInterface::pushCombatDamage(L, damage); - if (getScriptInterface()->protectedCall(L, 8, 4) != 0) { + if (LuaScriptInterface::protectedCall(L, 8, 4) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { damage.primary.value = std::abs(LuaScriptInterface::getNumber<int32_t>(L, -4)); @@ -949,11 +950,11 @@ void EventCallback::playerOnCombat(std::shared_ptr<Player> player, std::shared_p } } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void EventCallback::playerOnRequestQuestLog(std::shared_ptr<Player> player) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnRequestQuestLog(const std::shared_ptr<Player> &player) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnRequestQuestLog - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -961,7 +962,7 @@ void EventCallback::playerOnRequestQuestLog(std::shared_ptr<Player> player) cons return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -973,8 +974,8 @@ void EventCallback::playerOnRequestQuestLog(std::shared_ptr<Player> player) cons getScriptInterface()->callVoidFunction(1); } -void EventCallback::playerOnRequestQuestLine(std::shared_ptr<Player> player, uint16_t questId) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnRequestQuestLine(const std::shared_ptr<Player> &player, uint16_t questId) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::playerOnRequestQuestLine - " "Player {} questId {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -982,7 +983,7 @@ void EventCallback::playerOnRequestQuestLine(std::shared_ptr<Player> player, uin return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -996,13 +997,13 @@ void EventCallback::playerOnRequestQuestLine(std::shared_ptr<Player> player, uin getScriptInterface()->callVoidFunction(2); } -void EventCallback::playerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnInventoryUpdate(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool equip) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[{}] Call stack overflow", __FUNCTION__); return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1020,13 +1021,13 @@ void EventCallback::playerOnInventoryUpdate(std::shared_ptr<Player> player, std: getScriptInterface()->callVoidFunction(4); } -bool EventCallback::playerOnRotateItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &position) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::playerOnRotateItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const Position &position) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[{}] Call stack overflow", __FUNCTION__); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1043,8 +1044,8 @@ bool EventCallback::playerOnRotateItem(std::shared_ptr<Player> player, std::shar return getScriptInterface()->callFunction(3); } -void EventCallback::playerOnWalk(std::shared_ptr<Player> player, Direction &dir) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnWalk(const std::shared_ptr<Player> &player, const Direction &dir) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::eventOnWalk - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1052,7 +1053,7 @@ void EventCallback::playerOnWalk(std::shared_ptr<Player> player, Direction &dir) return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1066,8 +1067,8 @@ void EventCallback::playerOnWalk(std::shared_ptr<Player> player, Direction &dir) getScriptInterface()->callVoidFunction(2); } -void EventCallback::playerOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::playerOnStorageUpdate(const std::shared_ptr<Player> &player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::eventOnStorageUpdate - " "Player {} key {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1075,7 +1076,7 @@ void EventCallback::playerOnStorageUpdate(std::shared_ptr<Player> player, const return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1113,8 +1114,8 @@ void EventCallback::playerOnThink(std::shared_ptr<Player> player, uint32_t inter } // Monster -void EventCallback::monsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::monsterOnDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::monsterOnDropLoot - " "Monster corpse {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1122,7 +1123,7 @@ void EventCallback::monsterOnDropLoot(std::shared_ptr<Monster> monster, std::sha return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1137,8 +1138,8 @@ void EventCallback::monsterOnDropLoot(std::shared_ptr<Monster> monster, std::sha return getScriptInterface()->callVoidFunction(2); } -void EventCallback::monsterPostDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::monsterPostDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::monsterPostDropLoot - " "Monster corpse {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1146,7 +1147,7 @@ void EventCallback::monsterPostDropLoot(std::shared_ptr<Monster> monster, std::s return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1161,65 +1162,8 @@ void EventCallback::monsterPostDropLoot(std::shared_ptr<Monster> monster, std::s return getScriptInterface()->callVoidFunction(2); } -void EventCallback::monsterOnSpawn(std::shared_ptr<Monster> monster, const Position &position) const { - if (!getScriptInterface()->reserveScriptEnv()) { - g_logger().error("{} - " - "Position {}" - ". Call stack overflow. Too many lua script calls being nested.", - __FUNCTION__, position.toString()); - return; - } - - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); - scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); - - lua_State* L = getScriptInterface()->getLuaState(); - getScriptInterface()->pushFunction(getScriptId()); - - LuaScriptInterface::pushUserdata<Monster>(L, monster); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - LuaScriptInterface::pushPosition(L, position); - - if (getScriptInterface()->protectedCall(L, 2, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - lua_pop(L, 1); - } - - getScriptInterface()->resetScriptEnv(); -} - -// Npc -void EventCallback::npcOnSpawn(std::shared_ptr<Npc> npc, const Position &position) const { - if (!getScriptInterface()->reserveScriptEnv()) { - g_logger().error("{} - " - "Position {}" - ". Call stack overflow. Too many lua script calls being nested.", - __FUNCTION__, position.toString()); - return; - } - - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); - scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); - - lua_State* L = getScriptInterface()->getLuaState(); - getScriptInterface()->pushFunction(getScriptId()); - - LuaScriptInterface::pushUserdata<Npc>(L, npc); - LuaScriptInterface::setMetatable(L, -1, "Npc"); - LuaScriptInterface::pushPosition(L, position); - - if (getScriptInterface()->protectedCall(L, 2, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - lua_pop(L, 1); - } - - getScriptInterface()->resetScriptEnv(); -} - -bool EventCallback::zoneBeforeCreatureEnter(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::zoneBeforeCreatureEnter(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::zoneBeforeCreatureEnter - " "Zone {} Creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1227,7 +1171,7 @@ bool EventCallback::zoneBeforeCreatureEnter(std::shared_ptr<Zone> zone, std::sha return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1242,8 +1186,8 @@ bool EventCallback::zoneBeforeCreatureEnter(std::shared_ptr<Zone> zone, std::sha return getScriptInterface()->callFunction(2); } -bool EventCallback::zoneBeforeCreatureLeave(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const { - if (!getScriptInterface()->reserveScriptEnv()) { +bool EventCallback::zoneBeforeCreatureLeave(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::zoneBeforeCreatureLeave - " "Zone {} Creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1251,7 +1195,7 @@ bool EventCallback::zoneBeforeCreatureLeave(std::shared_ptr<Zone> zone, std::sha return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1266,8 +1210,8 @@ bool EventCallback::zoneBeforeCreatureLeave(std::shared_ptr<Zone> zone, std::sha return getScriptInterface()->callFunction(2); } -void EventCallback::zoneAfterCreatureEnter(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::zoneAfterCreatureEnter(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::zoneAfterCreatureEnter - " "Zone {} Creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1275,7 +1219,7 @@ void EventCallback::zoneAfterCreatureEnter(std::shared_ptr<Zone> zone, std::shar return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -1290,8 +1234,8 @@ void EventCallback::zoneAfterCreatureEnter(std::shared_ptr<Zone> zone, std::shar getScriptInterface()->callVoidFunction(2); } -void EventCallback::zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const { - if (!getScriptInterface()->reserveScriptEnv()) { +void EventCallback::zoneAfterCreatureLeave(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[EventCallback::zoneAfterCreatureLeave - " "Zone {} Creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1299,7 +1243,7 @@ void EventCallback::zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shar return; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); diff --git a/src/lua/callbacks/event_callback.hpp b/src/lua/callbacks/event_callback.hpp index 9e65480c246..c7df7929774 100644 --- a/src/lua/callbacks/event_callback.hpp +++ b/src/lua/callbacks/event_callback.hpp @@ -13,7 +13,6 @@ #include "creatures/creatures_definitions.hpp" #include "items/items_definitions.hpp" #include "utils/utils_definitions.hpp" -#include "lua/scripts/scripts.hpp" class Creature; class Player; @@ -22,6 +21,25 @@ class Party; class ItemType; class Monster; class Zone; +class LuaScriptInterface; +class Thing; +class Item; +class Cylinder; +class Npc; +class Container; + +struct Position; +struct CombatDamage; +struct Outfit_t; + +enum Direction : uint8_t; +enum ReturnValue : uint16_t; +enum SpeakClasses : uint8_t; +enum Slots_t : uint8_t; +enum ZoneType_t : uint8_t; +enum skills_t : int8_t; +enum CombatType_t : uint8_t; +enum TextColor_t : uint8_t; /** * @class EventCallback @@ -31,19 +49,23 @@ class Zone; * registration, and execution of custom behavior tied to specific game events. * @note It inherits from the Script class, providing scripting capabilities. */ -class EventCallback : public Script { +class EventCallback { private: EventCallback_t m_callbackType = EventCallback_t::none; ///< The type of the event callback. std::string m_scriptTypeName; ///< The name associated with the script type. std::string m_callbackName; ///< The name of the callback. bool m_skipDuplicationCheck = false; ///< Whether the callback is silent error for already registered log error. + int32_t m_scriptId {}; + public: - /** - * @brief Constructor that initializes the EventCallback with a given script interface. - * @param scriptInterface Pointer to the LuaScriptInterface object. - */ - explicit EventCallback(LuaScriptInterface* scriptInterface, const std::string &callbackName, bool silentAlreadyRegistered); + explicit EventCallback(const std::string &callbackName, bool silentAlreadyRegistered); + + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; /** * @brief Retrieves the callback name. @@ -61,13 +83,13 @@ class EventCallback : public Script { * @brief Retrieves the script type name. * @return The script type name as a string. */ - std::string getScriptTypeName() const override; + std::string getScriptTypeName() const; /** * @brief Sets a new script type name. * @param newName The new name to set for the script type. */ - void setScriptTypeName(const std::string_view newName); + void setScriptTypeName(std::string_view newName); /** * @brief Retrieves the type of the event callback. @@ -93,60 +115,55 @@ class EventCallback : public Script { */ // Creature - bool creatureOnChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) const; - ReturnValue creatureOnAreaCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Tile> tile, bool aggressive) const; - ReturnValue creatureOnTargetCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target) const; - void creatureOnHear(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> speaker, const std::string &words, SpeakClasses type) const; - void creatureOnDrainHealth(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) const; + bool creatureOnChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) const; + ReturnValue creatureOnAreaCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile, bool aggressive) const; + ReturnValue creatureOnTargetCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target) const; + void creatureOnDrainHealth(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) const; void creatureOnCombat(std::shared_ptr<Creature> attacker, std::shared_ptr<Creature> target, CombatDamage &damage) const; // Party - bool partyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const; - bool partyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Player> player) const; - bool partyOnDisband(std::shared_ptr<Party> party) const; - void partyOnShareExperience(std::shared_ptr<Party> party, uint64_t &exp) const; + bool partyOnJoin(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) const; + bool partyOnLeave(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) const; + bool partyOnDisband(const std::shared_ptr<Party> &party) const; + void partyOnShareExperience(const std::shared_ptr<Party> &party, uint64_t &exp) const; // Player - bool playerOnBrowseField(std::shared_ptr<Player> player, const Position &position) const; - void playerOnLook(std::shared_ptr<Player> player, const Position &position, std::shared_ptr<Thing> thing, uint8_t stackpos, int32_t lookDistance) const; - void playerOnLookInBattleList(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, int32_t lookDistance) const; - void playerOnLookInTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> partner, std::shared_ptr<Item> item, int32_t lookDistance) const; - bool playerOnLookInShop(std::shared_ptr<Player> player, const ItemType* itemType, uint8_t count) const; - bool playerOnMoveItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) const; - void playerOnItemMoved(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) const; - void playerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t zone) const; - bool playerOnMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, const Position &fromPosition, const Position &toPosition) const; - void playerOnReportRuleViolation(std::shared_ptr<Player> player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) const; - void playerOnReportBug(std::shared_ptr<Player> player, const std::string &message, const Position &position, uint8_t category) const; - bool playerOnTurn(std::shared_ptr<Player> player, Direction direction) const; - bool playerOnTradeRequest(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item) const; - bool playerOnTradeAccept(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item, std::shared_ptr<Item> targetItem) const; - void playerOnGainExperience(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint64_t &exp, uint64_t rawExp) const; - void playerOnLoseExperience(std::shared_ptr<Player> player, uint64_t &exp) const; - void playerOnGainSkillTries(std::shared_ptr<Player> player, skills_t skill, uint64_t &tries) const; - void playerOnRemoveCount(std::shared_ptr<Player> player, std::shared_ptr<Item> item) const; - void playerOnRequestQuestLog(std::shared_ptr<Player> player) const; - void playerOnRequestQuestLine(std::shared_ptr<Player> player, uint16_t questId) const; - void playerOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) const; - void playerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage) const; - void playerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip) const; - bool playerOnRotateItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &position) const; - void playerOnWalk(std::shared_ptr<Player> player, Direction &dir) const; + bool playerOnBrowseField(const std::shared_ptr<Player> &player, const Position &position) const; + void playerOnLook(const std::shared_ptr<Player> &player, const Position &position, const std::shared_ptr<Thing> &thing, uint8_t stackpos, int32_t lookDistance) const; + void playerOnLookInBattleList(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, int32_t lookDistance) const; + void playerOnLookInTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &partner, const std::shared_ptr<Item> &item, int32_t lookDistance) const; + bool playerOnLookInShop(const std::shared_ptr<Player> &player, const ItemType* itemType, uint8_t count) const; + bool playerOnMoveItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) const; + void playerOnItemMoved(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) const; + void playerOnChangeZone(const std::shared_ptr<Player> &player, ZoneType_t zone) const; + bool playerOnMoveCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, const Position &fromPosition, const Position &toPosition) const; + void playerOnReportRuleViolation(const std::shared_ptr<Player> &player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) const; + void playerOnReportBug(const std::shared_ptr<Player> &player, const std::string &message, const Position &position, uint8_t category) const; + bool playerOnTurn(const std::shared_ptr<Player> &player, Direction direction) const; + bool playerOnTradeRequest(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item) const; + bool playerOnTradeAccept(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &targetItem) const; + void playerOnGainExperience(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint64_t &exp, uint64_t rawExp) const; + void playerOnLoseExperience(const std::shared_ptr<Player> &player, uint64_t &exp) const; + void playerOnGainSkillTries(const std::shared_ptr<Player> &player, skills_t skill, uint64_t &tries) const; + void playerOnRemoveCount(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) const; + void playerOnRequestQuestLog(const std::shared_ptr<Player> &player) const; + void playerOnRequestQuestLine(const std::shared_ptr<Player> &player, uint16_t questId) const; + void playerOnStorageUpdate(const std::shared_ptr<Player> &player, uint32_t key, int32_t value, int32_t oldValue, uint64_t currentTime) const; + void playerOnCombat(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, CombatDamage &damage) const; + void playerOnInventoryUpdate(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool equip) const; + bool playerOnRotateItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const Position &position) const; + void playerOnWalk(const std::shared_ptr<Player> &player, const Direction &dir) const; void playerOnThink(std::shared_ptr<Player> player, uint32_t interval) const; // Monster - void monsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const; - void monsterPostDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) const; - void monsterOnSpawn(std::shared_ptr<Monster> monster, const Position &position) const; - - // Npc - void npcOnSpawn(std::shared_ptr<Npc> npc, const Position &position) const; + void monsterOnDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse) const; + void monsterPostDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse) const; // Zone - bool zoneBeforeCreatureEnter(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const; - bool zoneBeforeCreatureLeave(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const; - void zoneAfterCreatureEnter(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const; - void zoneAfterCreatureLeave(std::shared_ptr<Zone> zone, std::shared_ptr<Creature> creature) const; + bool zoneBeforeCreatureEnter(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const; + bool zoneBeforeCreatureLeave(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const; + void zoneAfterCreatureEnter(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const; + void zoneAfterCreatureLeave(const std::shared_ptr<Zone> &zone, const std::shared_ptr<Creature> &creature) const; void mapOnLoad(const std::string &mapFullPath) const; }; diff --git a/src/lua/callbacks/events_callbacks.hpp b/src/lua/callbacks/events_callbacks.hpp index 8913ee1dc4b..df321bbd02d 100644 --- a/src/lua/callbacks/events_callbacks.hpp +++ b/src/lua/callbacks/events_callbacks.hpp @@ -11,7 +11,6 @@ #include "lua/callbacks/callbacks_definitions.hpp" #include "lua/callbacks/event_callback.hpp" -#include "lua/scripts/luascript.hpp" class EventCallback; @@ -81,7 +80,7 @@ class EventsCallbacks { } for (const auto &entry : it->second) { - if (entry.callback && entry.callback->isLoadedCallback()) { + if (entry.callback && entry.callback->isLoadedScriptId()) { std::invoke(callbackFunc, *entry.callback, args...); } } @@ -102,7 +101,7 @@ class EventsCallbacks { } for (const auto &entry : it->second) { - if (entry.callback && entry.callback->isLoadedCallback()) { + if (entry.callback && entry.callback->isLoadedScriptId()) { ReturnValue callbackResult = std::invoke(callbackFunc, *entry.callback, args...); if (callbackResult != RETURNVALUE_NOERROR) { return callbackResult; @@ -128,7 +127,7 @@ class EventsCallbacks { } for (const auto &entry : it->second) { - if (entry.callback && entry.callback->isLoadedCallback()) { + if (entry.callback && entry.callback->isLoadedScriptId()) { bool callbackResult = std::invoke(callbackFunc, *entry.callback, args...); allCallbacksSucceeded &= callbackResult; } diff --git a/src/lua/creature/actions.cpp b/src/lua/creature/actions.cpp index c754ffa637c..2ee02fac9ab 100644 --- a/src/lua/creature/actions.cpp +++ b/src/lua/creature/actions.cpp @@ -8,16 +8,27 @@ */ #include "lua/creature/actions.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/spells.hpp" +#include "creatures/players/player.hpp" +#include "enums/account_group_type.hpp" +#include "game/game.hpp" #include "items/bed.hpp" #include "items/containers/container.hpp" -#include "game/game.hpp" -#include "creatures/combat/spells.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "items/containers/rewards/reward.hpp" #include "items/containers/rewards/rewardchest.hpp" -#include "enums/account_group_type.hpp" +#include "lua/scripts/scripts.hpp" +#include "lib/di/container.hpp" Actions::Actions() = default; Actions::~Actions() = default; +Actions &Actions::getInstance() { + return inject<Actions>(); +} + void Actions::clear() { useItemMap.clear(); uniqueItemMap.clear(); @@ -25,7 +36,7 @@ void Actions::clear() { actionPositionMap.clear(); } -bool Actions::registerLuaItemEvent(const std::shared_ptr<Action> action) { +bool Actions::registerLuaItemEvent(const std::shared_ptr<Action> &action) { auto itemIdVector = action->getItemIdsVector(); if (itemIdVector.empty()) { return false; @@ -58,7 +69,7 @@ bool Actions::registerLuaItemEvent(const std::shared_ptr<Action> action) { return !itemIdVector.empty(); } -bool Actions::registerLuaUniqueEvent(const std::shared_ptr<Action> action) { +bool Actions::registerLuaUniqueEvent(const std::shared_ptr<Action> &action) { auto uniqueIdVector = action->getUniqueIdsVector(); if (uniqueIdVector.empty()) { return false; @@ -89,7 +100,7 @@ bool Actions::registerLuaUniqueEvent(const std::shared_ptr<Action> action) { return !uniqueIdVector.empty(); } -bool Actions::registerLuaActionEvent(const std::shared_ptr<Action> action) { +bool Actions::registerLuaActionEvent(const std::shared_ptr<Action> &action) { auto actionIdVector = action->getActionIdsVector(); if (actionIdVector.empty()) { return false; @@ -120,7 +131,7 @@ bool Actions::registerLuaActionEvent(const std::shared_ptr<Action> action) { return !actionIdVector.empty(); } -bool Actions::registerLuaPositionEvent(const std::shared_ptr<Action> action) { +bool Actions::registerLuaPositionEvent(const std::shared_ptr<Action> &action) { auto positionVector = action->getPositionsVector(); if (positionVector.empty()) { return false; @@ -149,7 +160,7 @@ bool Actions::registerLuaPositionEvent(const std::shared_ptr<Action> action) { return !positionVector.empty(); } -bool Actions::registerLuaEvent(const std::shared_ptr<Action> action) { +bool Actions::registerLuaEvent(const std::shared_ptr<Action> &action) { // Call all register lua events if (registerLuaItemEvent(action) || registerLuaUniqueEvent(action) || registerLuaActionEvent(action) || registerLuaPositionEvent(action)) { return true; @@ -165,7 +176,7 @@ bool Actions::registerLuaEvent(const std::shared_ptr<Action> action) { return false; } -ReturnValue Actions::canUse(std::shared_ptr<Player> player, const Position &pos) { +ReturnValue Actions::canUse(const std::shared_ptr<Player> &player, const Position &pos) const { if (pos.x != 0xFFFF) { const Position &playerPos = player->getPosition(); if (playerPos.z != pos.z) { @@ -179,15 +190,15 @@ ReturnValue Actions::canUse(std::shared_ptr<Player> player, const Position &pos) return RETURNVALUE_NOERROR; } -ReturnValue Actions::canUse(std::shared_ptr<Player> player, const Position &pos, std::shared_ptr<Item> item) { - const std::shared_ptr<Action> action = getAction(item); +ReturnValue Actions::canUse(const std::shared_ptr<Player> &player, const Position &pos, const std::shared_ptr<Item> &item) { + const auto &action = getAction(item); if (action != nullptr) { return action->canExecuteAction(player, pos); } return RETURNVALUE_NOERROR; } -ReturnValue Actions::canUseFar(std::shared_ptr<Creature> creature, const Position &toPos, bool checkLineOfSight, bool checkFloor) { +ReturnValue Actions::canUseFar(const std::shared_ptr<Creature> &creature, const Position &toPos, bool checkLineOfSight, bool checkFloor) const { if (toPos.x == 0xFFFF) { return RETURNVALUE_NOERROR; } @@ -208,31 +219,30 @@ ReturnValue Actions::canUseFar(std::shared_ptr<Creature> creature, const Positio return RETURNVALUE_NOERROR; } -std::shared_ptr<Action> Actions::getAction(std::shared_ptr<Item> item) { +std::shared_ptr<Action> Actions::getAction(const std::shared_ptr<Item> &item) { if (item->hasAttribute(ItemAttribute_t::UNIQUEID)) { - auto it = uniqueItemMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::UNIQUEID)); + const auto it = uniqueItemMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::UNIQUEID)); if (it != uniqueItemMap.end()) { return it->second; } } if (item->hasAttribute(ItemAttribute_t::ACTIONID)) { - auto it = actionItemMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)); + const auto it = actionItemMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)); if (it != actionItemMap.end()) { return it->second; } } - auto it = useItemMap.find(item->getID()); + const auto it = useItemMap.find(item->getID()); if (it != useItemMap.end()) { return it->second; } - if (auto iteratePositions = actionPositionMap.find(item->getPosition()); + if (const auto iteratePositions = actionPositionMap.find(item->getPosition()); iteratePositions != actionPositionMap.end()) { - if (std::shared_ptr<Tile> tile = item->getTile(); - tile) { - if (std::shared_ptr<Player> player = item->getHoldingPlayer(); + if (const auto &tile = item->getTile()) { + if (const auto &player = item->getHoldingPlayer(); player && item->getTopParent() == player) { g_logger().debug("[Actions::getAction] - The position only is valid for use item in the map, player name {}", player->getName()); return nullptr; @@ -246,8 +256,8 @@ std::shared_ptr<Action> Actions::getAction(std::shared_ptr<Item> item) { return g_spells().getRuneSpell(item->getID()); } -ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Position &pos, uint8_t index, std::shared_ptr<Item> item, bool isHotkey) { - if (std::shared_ptr<Door> door = item->getDoor()) { +ReturnValue Actions::internalUseItem(const std::shared_ptr<Player> &player, const Position &pos, uint8_t index, const std::shared_ptr<Item> &item, bool isHotkey) { + if (const auto &door = item->getDoor()) { if (!door->canUse(player)) { return RETURNVALUE_CANNOTUSETHISOBJECT; } @@ -256,7 +266,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit auto itemId = item->getID(); const ItemType &itemType = Item::items[itemId]; auto transformTo = itemType.m_transformOnUse; - const std::shared_ptr<Action> action = getAction(item); + const auto &action = getAction(item); if (!action && transformTo > 0 && itemId != transformTo) { if (g_game().transformItem(item, transformTo) == nullptr) { g_logger().warn("[{}] item with id {} failed to transform to item {}", __FUNCTION__, itemId, transformTo); @@ -269,7 +279,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit } if (action != nullptr) { - if (action->isLoadedCallback()) { + if (action->isLoadedScriptId()) { if (action->executeUse(player, item, pos, nullptr, pos, isHotkey)) { return RETURNVALUE_NOERROR; } @@ -281,7 +291,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit } } - if (std::shared_ptr<BedItem> bed = item->getBed()) { + if (const auto &bed = item->getBed()) { if (!bed->canUse(player)) { return RETURNVALUE_CANNOTUSETHISOBJECT; } @@ -294,12 +304,12 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit return RETURNVALUE_NOERROR; } - if (std::shared_ptr<Container> container = item->getContainer()) { + if (const auto &container = item->getContainer()) { std::shared_ptr<Container> openContainer; // depot container - if (std::shared_ptr<DepotLocker> depot = container->getDepotLocker()) { - std::shared_ptr<DepotLocker> myDepotLocker = player->getDepotLocker(depot->getDepotId()); + if (const auto &depot = container->getDepotLocker()) { + const auto &myDepotLocker = player->getDepotLocker(depot->getDepotId()); myDepotLocker->setParent(depot->getParent()->getTile()); openContainer = myDepotLocker; player->setLastDepotId(depot->getDepotId()); @@ -313,7 +323,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit player->removeEmptyRewards(); } - std::shared_ptr<RewardChest> playerRewardChest = player->getRewardChest(); + const auto &playerRewardChest = player->getRewardChest(); if (playerRewardChest->empty()) { return RETURNVALUE_REWARDCHESTISEMPTY; } @@ -326,10 +336,10 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit openContainer = playerRewardChest; } - auto rewardId = container->getAttribute<time_t>(ItemAttribute_t::DATE); + const auto rewardId = container->getAttribute<time_t>(ItemAttribute_t::DATE); // Reward container proxy created when the boss dies if (container->getID() == ITEM_REWARD_CONTAINER && !container->getReward()) { - auto reward = player->getReward(rewardId, false); + const auto &reward = player->getReward(rewardId, false); if (!reward) { return RETURNVALUE_THISISIMPOSSIBLE; } @@ -340,13 +350,13 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit openContainer = reward; } - uint32_t corpseOwner = container->getCorpseOwner(); + const uint32_t corpseOwner = container->getCorpseOwner(); if (container->isRewardCorpse()) { // only players who participated in the fight can open the corpse if (player->getGroup()->id >= GROUP_TYPE_GAMEMASTER) { return RETURNVALUE_YOUCANTOPENCORPSEADM; } - auto reward = player->getReward(rewardId, false); + const auto &reward = player->getReward(rewardId, false); if (!reward) { return RETURNVALUE_YOUARENOTTHEOWNER; } @@ -358,7 +368,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit } // open/close container - int32_t oldContainerId = player->getContainerID(openContainer); + const int32_t oldContainerId = player->getContainerID(openContainer); if (oldContainerId != -1) { player->onCloseContainer(openContainer); player->closeContainer(oldContainerId); @@ -386,7 +396,7 @@ ReturnValue Actions::internalUseItem(std::shared_ptr<Player> player, const Posit return RETURNVALUE_CANNOTUSETHISOBJECT; } -bool Actions::useItem(std::shared_ptr<Player> player, const Position &pos, uint8_t index, std::shared_ptr<Item> item, bool isHotkey) { +bool Actions::useItem(const std::shared_ptr<Player> &player, const Position &pos, uint8_t index, const std::shared_ptr<Item> &item, bool isHotkey) { const ItemType &it = Item::items[item->getID()]; if (it.isRune() || it.type == ITEM_TYPE_POTION) { if (player->walkExhausted()) { @@ -395,7 +405,7 @@ bool Actions::useItem(std::shared_ptr<Player> player, const Position &pos, uint8 } } if (isHotkey) { - uint16_t subType = item->getSubType(); + const uint16_t subType = item->getSubType(); showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), subType != item->getItemCount() ? subType : -1)); } @@ -418,7 +428,7 @@ bool Actions::useItem(std::shared_ptr<Player> player, const Position &pos, uint8 return true; } -bool Actions::useItemEx(std::shared_ptr<Player> player, const Position &fromPos, const Position &toPos, uint8_t toStackPos, std::shared_ptr<Item> item, bool isHotkey, std::shared_ptr<Creature> creature /* = nullptr*/) { +bool Actions::useItemEx(const std::shared_ptr<Player> &player, const Position &fromPos, const Position &toPos, uint8_t toStackPos, const std::shared_ptr<Item> &item, bool isHotkey, const std::shared_ptr<Creature> &creature /* = nullptr*/) { const ItemType &it = Item::items[item->getID()]; if (it.isRune() || it.type == ITEM_TYPE_POTION) { if (player->walkExhausted()) { @@ -440,7 +450,7 @@ bool Actions::useItemEx(std::shared_ptr<Player> player, const Position &fromPos, } if (isHotkey) { - uint16_t subType = item->getSubType(); + const uint16_t subType = item->getSubType(); showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), subType != item->getItemCount() ? subType : -1)); } @@ -470,7 +480,7 @@ bool Actions::useItemEx(std::shared_ptr<Player> player, const Position &fromPos, return true; } -void Actions::showUseHotkeyMessage(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint32_t count) { +void Actions::showUseHotkeyMessage(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint32_t count) { std::ostringstream ss; const ItemType &it = Item::items[item->getID()]; @@ -491,10 +501,36 @@ void Actions::showUseHotkeyMessage(std::shared_ptr<Player> player, std::shared_p */ // Action constructor -Action::Action(LuaScriptInterface* interface) : - Script(interface) { } +Action::Action() = default; + +LuaScriptInterface* Action::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool Action::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t Action::getScriptId() const { + return m_scriptId; +} + +void Action::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool Action::isLoadedScriptId() const { + return m_scriptId != 0; +} -ReturnValue Action::canExecuteAction(std::shared_ptr<Player> player, const Position &toPos) { +ReturnValue Action::canExecuteAction(const std::shared_ptr<Player> &player, const Position &toPos) { if (!allowFarUse) { return g_actions().canUse(player, toPos); } @@ -502,23 +538,23 @@ ReturnValue Action::canExecuteAction(std::shared_ptr<Player> player, const Posit return g_actions().canUseFar(player, toPos, checkLineOfSight, checkFloor); } -std::shared_ptr<Thing> Action::getTarget(std::shared_ptr<Player> player, std::shared_ptr<Creature> targetCreature, const Position &toPosition, uint8_t toStackPos) const { +std::shared_ptr<Thing> Action::getTarget(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &targetCreature, const Position &toPosition, uint8_t toStackPos) const { if (targetCreature != nullptr) { return targetCreature; } return g_game().internalGetThing(player, toPosition, toStackPos, 0, STACKPOS_USETARGET); } -bool Action::executeUse(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &fromPosition, std::shared_ptr<Thing> target, const Position &toPosition, bool isHotkey) { +bool Action::executeUse(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const Position &fromPosition, const std::shared_ptr<Thing> &target, const Position &toPosition, bool isHotkey) { // onUse(player, item, fromPosition, target, toPosition, isHotkey) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Action::executeUse - Player {}, on item {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), item->getName()); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); diff --git a/src/lua/creature/actions.hpp b/src/lua/creature/actions.hpp index 81a7754a5b1..f0d73811354 100644 --- a/src/lua/creature/actions.hpp +++ b/src/lua/creature/actions.hpp @@ -9,19 +9,23 @@ #pragma once -#include "lua/scripts/scripts.hpp" #include "declarations.hpp" -#include "lua/scripts/luascript.hpp" class Action; -class Position; +class LuaScriptInterface; +class Player; +class Item; +class Creature; +class Thing; -class Action : public Script { +struct Position; + +class Action { public: - explicit Action(LuaScriptInterface* interface); + explicit Action(); // Scripting - virtual bool executeUse(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const Position &fromPosition, std::shared_ptr<Thing> target, const Position &toPosition, bool isHotkey); + virtual bool executeUse(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const Position &fromPosition, const std::shared_ptr<Thing> &target, const Position &toPosition, bool isHotkey); bool getAllowFarUse() const { return allowFarUse; @@ -96,22 +100,26 @@ class Action : public Script { positions.emplace_back(pos); } - virtual ReturnValue canExecuteAction(std::shared_ptr<Player> player, const Position &toPos); + virtual ReturnValue canExecuteAction(const std::shared_ptr<Player> &player, const Position &toPos); virtual bool hasOwnErrorHandler() { return false; } - virtual std::shared_ptr<Thing> getTarget(std::shared_ptr<Player> player, std::shared_ptr<Creature> targetCreature, const Position &toPosition, uint8_t toStackPos) const; + virtual std::shared_ptr<Thing> getTarget(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &targetCreature, const Position &toPosition, uint8_t toStackPos) const; + + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; private: - std::string getScriptTypeName() const override { - return "onUse"; - } + int32_t m_scriptId {}; std::function<bool( - std::shared_ptr<Player> player, std::shared_ptr<Item> item, - const Position &fromPosition, std::shared_ptr<Thing> target, + const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, + const Position &fromPosition, const std::shared_ptr<Thing> &target, const Position &toPosition, bool isHotkey )> useFunction = nullptr; @@ -130,7 +138,7 @@ class Action : public Script { friend class Actions; }; -class Actions final : public Scripts { +class Actions { public: Actions(); ~Actions(); @@ -139,28 +147,26 @@ class Actions final : public Scripts { Actions(const Actions &) = delete; Actions &operator=(const Actions &) = delete; - static Actions &getInstance() { - return inject<Actions>(); - } + static Actions &getInstance(); - bool useItem(std::shared_ptr<Player> player, const Position &pos, uint8_t index, std::shared_ptr<Item> item, bool isHotkey); - bool useItemEx(std::shared_ptr<Player> player, const Position &fromPos, const Position &toPos, uint8_t toStackPos, std::shared_ptr<Item> item, bool isHotkey, std::shared_ptr<Creature> creature = nullptr); + bool useItem(const std::shared_ptr<Player> &player, const Position &pos, uint8_t index, const std::shared_ptr<Item> &item, bool isHotkey); + bool useItemEx(const std::shared_ptr<Player> &player, const Position &fromPos, const Position &toPos, uint8_t toStackPos, const std::shared_ptr<Item> &item, bool isHotkey, const std::shared_ptr<Creature> &creature = nullptr); - ReturnValue canUse(std::shared_ptr<Player> player, const Position &pos); - ReturnValue canUse(std::shared_ptr<Player> player, const Position &pos, std::shared_ptr<Item> item); - ReturnValue canUseFar(std::shared_ptr<Creature> creature, const Position &toPos, bool checkLineOfSight, bool checkFloor); + ReturnValue canUse(const std::shared_ptr<Player> &player, const Position &pos) const; + ReturnValue canUse(const std::shared_ptr<Player> &player, const Position &pos, const std::shared_ptr<Item> &item); + ReturnValue canUseFar(const std::shared_ptr<Creature> &creature, const Position &toPos, bool checkLineOfSight, bool checkFloor) const; - bool registerLuaItemEvent(const std::shared_ptr<Action> action); - bool registerLuaUniqueEvent(const std::shared_ptr<Action> action); - bool registerLuaActionEvent(const std::shared_ptr<Action> action); - bool registerLuaPositionEvent(const std::shared_ptr<Action> action); - bool registerLuaEvent(const std::shared_ptr<Action> action); + bool registerLuaItemEvent(const std::shared_ptr<Action> &action); + bool registerLuaUniqueEvent(const std::shared_ptr<Action> &action); + bool registerLuaActionEvent(const std::shared_ptr<Action> &action); + bool registerLuaPositionEvent(const std::shared_ptr<Action> &action); + bool registerLuaEvent(const std::shared_ptr<Action> &action); // Clear maps for reloading void clear(); private: - bool hasPosition(Position position) const { - if (auto it = actionPositionMap.find(position); + bool hasPosition(const Position &position) const { + if (const auto it = actionPositionMap.find(position); it != actionPositionMap.end()) { return true; } @@ -171,48 +177,48 @@ class Actions final : public Scripts { return actionPositionMap; } - void setPosition(Position position, std::shared_ptr<Action> action) { + void setPosition(const Position &position, const std::shared_ptr<Action> &action) { actionPositionMap.try_emplace(position, action); } bool hasItemId(uint16_t itemId) const { - if (auto it = useItemMap.find(itemId); + if (const auto it = useItemMap.find(itemId); it != useItemMap.end()) { return true; } return false; } - void setItemId(uint16_t itemId, const std::shared_ptr<Action> action) { + void setItemId(uint16_t itemId, const std::shared_ptr<Action> &action) { useItemMap.try_emplace(itemId, action); } bool hasUniqueId(uint16_t uniqueId) const { - if (auto it = uniqueItemMap.find(uniqueId); + if (const auto it = uniqueItemMap.find(uniqueId); it != uniqueItemMap.end()) { return true; } return false; } - void setUniqueId(uint16_t uniqueId, const std::shared_ptr<Action> action) { + void setUniqueId(uint16_t uniqueId, const std::shared_ptr<Action> &action) { uniqueItemMap.try_emplace(uniqueId, action); } bool hasActionId(uint16_t actionId) const { - if (auto it = actionItemMap.find(actionId); + if (const auto it = actionItemMap.find(actionId); it != actionItemMap.end()) { return true; } return false; } - void setActionId(uint16_t actionId, const std::shared_ptr<Action> action) { + void setActionId(uint16_t actionId, const std::shared_ptr<Action> &action) { actionItemMap.try_emplace(actionId, action); } - ReturnValue internalUseItem(std::shared_ptr<Player> player, const Position &pos, uint8_t index, std::shared_ptr<Item> item, bool isHotkey); - static void showUseHotkeyMessage(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint32_t count); + ReturnValue internalUseItem(const std::shared_ptr<Player> &player, const Position &pos, uint8_t index, const std::shared_ptr<Item> &item, bool isHotkey); + static void showUseHotkeyMessage(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint32_t count); using ActionUseMap = std::map<uint16_t, std::shared_ptr<Action>>; ActionUseMap useItemMap; @@ -220,7 +226,7 @@ class Actions final : public Scripts { ActionUseMap actionItemMap; std::map<Position, std::shared_ptr<Action>> actionPositionMap; - std::shared_ptr<Action> getAction(std::shared_ptr<Item> item); + std::shared_ptr<Action> getAction(const std::shared_ptr<Item> &item); }; constexpr auto g_actions = Actions::getInstance; diff --git a/src/lua/creature/creatureevent.cpp b/src/lua/creature/creatureevent.cpp index 3b7dfdceb4c..c13c8180556 100644 --- a/src/lua/creature/creatureevent.cpp +++ b/src/lua/creature/creatureevent.cpp @@ -8,16 +8,19 @@ */ #include "lua/creature/creatureevent.hpp" -#include "utils/tools.hpp" + #include "creatures/players/player.hpp" +#include "items/item.hpp" +#include "lua/scripts/scripts.hpp" +#include "lib/di/container.hpp" void CreatureEvents::clear() { - for (auto &[name, event] : creatureEvents) { + for (const auto &[name, event] : creatureEvents) { event->clearEvent(); } } -bool CreatureEvents::registerLuaEvent(const std::shared_ptr<CreatureEvent> creatureEvent) { +bool CreatureEvents::registerLuaEvent(const std::shared_ptr<CreatureEvent> &creatureEvent) { if (creatureEvent->getEventType() == CREATURE_EVENT_NONE) { g_logger().error( "[{}] - Trying to register event without type for script: {}", @@ -27,7 +30,7 @@ bool CreatureEvents::registerLuaEvent(const std::shared_ptr<CreatureEvent> creat return false; } - const std::shared_ptr<CreatureEvent> oldEvent = getEventByName(creatureEvent->getName(), false); + const auto &oldEvent = getEventByName(creatureEvent->getName(), false); if (oldEvent) { // if there was an event with the same that is not loaded //(happens when realoading), it is reused @@ -44,7 +47,7 @@ bool CreatureEvents::registerLuaEvent(const std::shared_ptr<CreatureEvent> creat } std::shared_ptr<CreatureEvent> CreatureEvents::getEventByName(const std::string &name, bool forceLoaded /*= true*/) { - auto it = creatureEvents.find(name); + const auto it = creatureEvents.find(name); if (it != creatureEvents.end()) { if (!forceLoaded || it->second->isLoaded()) { return it->second; @@ -53,7 +56,11 @@ std::shared_ptr<CreatureEvent> CreatureEvents::getEventByName(const std::string return nullptr; } -bool CreatureEvents::playerLogin(std::shared_ptr<Player> player) const { +CreatureEvents &CreatureEvents::getInstance() { + return inject<CreatureEvents>(); +} + +bool CreatureEvents::playerLogin(const std::shared_ptr<Player> &player) const { // fire global event if is registered for (const auto &it : creatureEvents) { if (it.second->getEventType() == CREATURE_EVENT_LOGIN) { @@ -65,7 +72,7 @@ bool CreatureEvents::playerLogin(std::shared_ptr<Player> player) const { return true; } -bool CreatureEvents::playerLogout(std::shared_ptr<Player> player) const { +bool CreatureEvents::playerLogout(const std::shared_ptr<Player> &player) const { // fire global event if is registered for (const auto &it : creatureEvents) { if (it.second->getEventType() == CREATURE_EVENT_LOGOUT) { @@ -78,7 +85,7 @@ bool CreatureEvents::playerLogout(std::shared_ptr<Player> player) const { } bool CreatureEvents::playerAdvance( - std::shared_ptr<Player> player, + const std::shared_ptr<Player> &player, skills_t skill, uint32_t oldLevel, uint32_t newLevel @@ -99,8 +106,34 @@ bool CreatureEvents::playerAdvance( ======================= */ -CreatureEvent::CreatureEvent(LuaScriptInterface* interface) : - Script(interface) { } +CreatureEvent::CreatureEvent() = default; + +LuaScriptInterface* CreatureEvent::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool CreatureEvent::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t CreatureEvent::getScriptId() const { + return m_scriptId; +} + +void CreatureEvent::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool CreatureEvent::isLoadedScriptId() const { + return m_scriptId != 0; +} void CreatureEvents::removeInvalidEvents() { std::erase_if(creatureEvents, [](const auto &pair) { @@ -149,34 +182,30 @@ std::string CreatureEvent::getScriptTypeName() const { case CREATURE_EVENT_NONE: default: - return std::string(); + return {}; } } -void CreatureEvent::copyEvent(const std::shared_ptr<CreatureEvent> creatureEvent) { +void CreatureEvent::copyEvent(const std::shared_ptr<CreatureEvent> &creatureEvent) { setScriptId(creatureEvent->getScriptId()); - setScriptInterface(creatureEvent->getScriptInterface()); - setLoadedCallback(creatureEvent->isLoadedCallback()); loaded = creatureEvent->loaded; } void CreatureEvent::clearEvent() { setScriptId(0); - setScriptInterface(nullptr); - setLoadedCallback(false); loaded = false; } -bool CreatureEvent::executeOnLogin(std::shared_ptr<Player> player) const { +bool CreatureEvent::executeOnLogin(const std::shared_ptr<Player> &player) const { // onLogin(player) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnLogin - Player {} event {}]" "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -187,16 +216,16 @@ bool CreatureEvent::executeOnLogin(std::shared_ptr<Player> player) const { return getScriptInterface()->callFunction(1); } -bool CreatureEvent::executeOnLogout(std::shared_ptr<Player> player) const { +bool CreatureEvent::executeOnLogout(const std::shared_ptr<Player> &player) const { // onLogout(player) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnLogout - Player {} event {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -207,16 +236,16 @@ bool CreatureEvent::executeOnLogout(std::shared_ptr<Player> player) const { return getScriptInterface()->callFunction(1); } -bool CreatureEvent::executeOnThink(std::shared_ptr<Creature> creature, uint32_t interval) const { +bool CreatureEvent::executeOnThink(const std::shared_ptr<Creature> &creature, uint32_t interval) const { // onThink(creature, interval) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnThink - Creature {} event {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -229,16 +258,16 @@ bool CreatureEvent::executeOnThink(std::shared_ptr<Creature> creature, uint32_t return getScriptInterface()->callFunction(2); } -bool CreatureEvent::executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer, int realDamage) const { +bool CreatureEvent::executeOnPrepareDeath(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &killer, int realDamage) const { // onPrepareDeath(creature, killer) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnPrepareDeath - Creature {} killer {}" " event {}] Call stack overflow. Too many lua script calls being nested.", creature->getName(), killer->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -260,16 +289,16 @@ bool CreatureEvent::executeOnPrepareDeath(std::shared_ptr<Creature> creature, st return getScriptInterface()->callFunction(3); } -bool CreatureEvent::executeOnDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Item> corpse, std::shared_ptr<Creature> killer, std::shared_ptr<Creature> mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const { +bool CreatureEvent::executeOnDeath(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &corpse, const std::shared_ptr<Creature> &killer, const std::shared_ptr<Creature> &mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const { // onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnDeath - Creature {} killer {} event {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), killer->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -300,16 +329,16 @@ bool CreatureEvent::executeOnDeath(std::shared_ptr<Creature> creature, std::shar return getScriptInterface()->callFunction(6); } -bool CreatureEvent::executeAdvance(std::shared_ptr<Player> player, skills_t skill, uint32_t oldLevel, uint32_t newLevel) const { +bool CreatureEvent::executeAdvance(const std::shared_ptr<Player> &player, skills_t skill, uint32_t oldLevel, uint32_t newLevel) const { // onAdvance(player, skill, oldLevel, newLevel) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeAdvance - Player {} event {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -327,19 +356,19 @@ bool CreatureEvent::executeAdvance(std::shared_ptr<Player> player, skills_t skil /** * @deprecated Prefer using registered onDeath events instead for better performance. */ -void CreatureEvent::executeOnKill(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target, bool lastHit) const { +void CreatureEvent::executeOnKill(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target, bool lastHit) const { // onKill(creature, target, lastHit) g_logger().warn("[CreatureEvent::executeOnKill - Creature {} target {} event {}] " "Deprecated use of onKill event. Use registered onDeath events instead for better performance.", creature->getName(), target->getName(), getName()); - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeOnKill - Creature {} target {} event {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName(), target->getName(), getName()); return; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -353,9 +382,9 @@ void CreatureEvent::executeOnKill(std::shared_ptr<Creature> creature, std::share getScriptInterface()->callVoidFunction(3); } -void CreatureEvent::executeModalWindow(std::shared_ptr<Player> player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId) const { +void CreatureEvent::executeModalWindow(const std::shared_ptr<Player> &player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId) const { // onModalWindow(player, modalWindowId, buttonId, choiceId) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeModalWindow - " "Player {} modaw window id {} event {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -363,7 +392,7 @@ void CreatureEvent::executeModalWindow(std::shared_ptr<Player> player, uint32_t return; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -379,16 +408,16 @@ void CreatureEvent::executeModalWindow(std::shared_ptr<Player> player, uint32_t getScriptInterface()->callVoidFunction(4); } -bool CreatureEvent::executeTextEdit(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const std::string &text) const { +bool CreatureEvent::executeTextEdit(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::string &text) const { // onTextEdit(player, item, text) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeTextEdit - Player {} event {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -403,9 +432,9 @@ bool CreatureEvent::executeTextEdit(std::shared_ptr<Player> player, std::shared_ return getScriptInterface()->callFunction(3); } -void CreatureEvent::executeHealthChange(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatDamage &damage) const { +void CreatureEvent::executeHealthChange(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatDamage &damage) const { // onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeHealthChange - " "Creature {} attacker {} event {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -413,7 +442,7 @@ void CreatureEvent::executeHealthChange(std::shared_ptr<Creature> creature, std: return; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -430,7 +459,7 @@ void CreatureEvent::executeHealthChange(std::shared_ptr<Creature> creature, std: LuaScriptInterface::pushCombatDamage(L, damage); - if (getScriptInterface()->protectedCall(L, 7, 4) != 0) { + if (LuaScriptInterface::protectedCall(L, 7, 4) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { damage.primary.value = std::abs(LuaScriptInterface::getNumber<int32_t>(L, -4)); @@ -445,12 +474,12 @@ void CreatureEvent::executeHealthChange(std::shared_ptr<Creature> creature, std: } } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void CreatureEvent::executeManaChange(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatDamage &damage) const { +void CreatureEvent::executeManaChange(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatDamage &damage) const { // onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeManaChange - " "Creature {} attacker {} event {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -458,7 +487,7 @@ void CreatureEvent::executeManaChange(std::shared_ptr<Creature> creature, std::s return; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -475,7 +504,7 @@ void CreatureEvent::executeManaChange(std::shared_ptr<Creature> creature, std::s LuaScriptInterface::pushCombatDamage(L, damage); - if (getScriptInterface()->protectedCall(L, 7, 4) != 0) { + if (LuaScriptInterface::protectedCall(L, 7, 4) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { damage.primary.value = LuaScriptInterface::getNumber<int32_t>(L, -4); @@ -485,12 +514,12 @@ void CreatureEvent::executeManaChange(std::shared_ptr<Creature> creature, std::s lua_pop(L, 4); } - getScriptInterface()->resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void CreatureEvent::executeExtendedOpcode(std::shared_ptr<Player> player, uint8_t opcode, const std::string &buffer) const { +void CreatureEvent::executeExtendedOpcode(const std::shared_ptr<Player> &player, uint8_t opcode, const std::string &buffer) const { // onExtendedOpcode(player, opcode, buffer) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[CreatureEvent::executeExtendedOpcode - " "Player {} event {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -498,7 +527,7 @@ void CreatureEvent::executeExtendedOpcode(std::shared_ptr<Player> player, uint8_ return; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); diff --git a/src/lua/creature/creatureevent.hpp b/src/lua/creature/creatureevent.hpp index e34bd8eb75e..1d5c612a68c 100644 --- a/src/lua/creature/creatureevent.hpp +++ b/src/lua/creature/creatureevent.hpp @@ -9,16 +9,21 @@ #pragma once -#include "declarations.hpp" -#include "lib/di/container.hpp" -#include "lua/scripts/luascript.hpp" -#include "lua/scripts/scripts.hpp" +#include "lua/lua_definitions.hpp" class CreatureEvent; +class LuaScriptInterface; +class Creature; +class Player; +class Item; -class CreatureEvent final : public Script { +struct CombatDamage; + +enum skills_t : int8_t; + +class CreatureEvent { public: - explicit CreatureEvent(LuaScriptInterface* interface); + explicit CreatureEvent(); CreatureEventType_t getEventType() const { return type; @@ -40,32 +45,38 @@ class CreatureEvent final : public Script { } void clearEvent(); - void copyEvent(const std::shared_ptr<CreatureEvent> creatureEvent); + void copyEvent(const std::shared_ptr<CreatureEvent> &creatureEvent); // scripting - bool executeOnLogin(std::shared_ptr<Player> player) const; - bool executeOnLogout(std::shared_ptr<Player> player) const; - bool executeOnThink(std::shared_ptr<Creature> creature, uint32_t interval) const; - bool executeOnPrepareDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> killer, int realDamage) const; - bool executeOnDeath(std::shared_ptr<Creature> creature, std::shared_ptr<Item> corpse, std::shared_ptr<Creature> killer, std::shared_ptr<Creature> mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const; - void executeOnKill(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target, bool lastHit) const; - bool executeAdvance(std::shared_ptr<Player> player, skills_t, uint32_t, uint32_t) const; - void executeModalWindow(std::shared_ptr<Player> player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId) const; - bool executeTextEdit(std::shared_ptr<Player> player, std::shared_ptr<Item> item, const std::string &text) const; - void executeHealthChange(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatDamage &damage) const; - void executeManaChange(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatDamage &damage) const; - void executeExtendedOpcode(std::shared_ptr<Player> player, uint8_t opcode, const std::string &buffer) const; - // + bool executeOnLogin(const std::shared_ptr<Player> &player) const; + bool executeOnLogout(const std::shared_ptr<Player> &player) const; + bool executeOnThink(const std::shared_ptr<Creature> &creature, uint32_t interval) const; + bool executeOnPrepareDeath(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &killer, int realDamage) const; + bool executeOnDeath(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &corpse, const std::shared_ptr<Creature> &killer, const std::shared_ptr<Creature> &mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) const; + void executeOnKill(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target, bool lastHit) const; + bool executeAdvance(const std::shared_ptr<Player> &player, skills_t, uint32_t, uint32_t) const; + void executeModalWindow(const std::shared_ptr<Player> &player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId) const; + bool executeTextEdit(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, const std::string &text) const; + void executeHealthChange(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatDamage &damage) const; + void executeManaChange(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatDamage &damage) const; + void executeExtendedOpcode(const std::shared_ptr<Player> &player, uint8_t opcode, const std::string &buffer) const; + + std::string getScriptTypeName() const; + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; private: - std::string getScriptTypeName() const override; + int32_t m_scriptId {}; std::string eventName; CreatureEventType_t type = CREATURE_EVENT_NONE; bool loaded = false; }; -class CreatureEvents final : public Scripts { +class CreatureEvents { public: CreatureEvents() = default; @@ -73,18 +84,16 @@ class CreatureEvents final : public Scripts { CreatureEvents(const CreatureEvents &) = delete; CreatureEvents &operator=(const CreatureEvents &) = delete; - static CreatureEvents &getInstance() { - return inject<CreatureEvents>(); - } + static CreatureEvents &getInstance(); // global events - bool playerLogin(std::shared_ptr<Player> player) const; - bool playerLogout(std::shared_ptr<Player> player) const; - bool playerAdvance(std::shared_ptr<Player> player, skills_t, uint32_t, uint32_t) const; + bool playerLogin(const std::shared_ptr<Player> &player) const; + bool playerLogout(const std::shared_ptr<Player> &player) const; + bool playerAdvance(const std::shared_ptr<Player> &player, skills_t, uint32_t, uint32_t) const; std::shared_ptr<CreatureEvent> getEventByName(const std::string &name, bool forceLoaded = true); - bool registerLuaEvent(const std::shared_ptr<CreatureEvent> event); + bool registerLuaEvent(const std::shared_ptr<CreatureEvent> &event); void removeInvalidEvents(); void clear(); diff --git a/src/lua/creature/events.cpp b/src/lua/creature/events.cpp index 1f101204164..9e03858107b 100644 --- a/src/lua/creature/events.cpp +++ b/src/lua/creature/events.cpp @@ -8,9 +8,16 @@ */ #include "lua/creature/events.hpp" -#include "utils/tools.hpp" -#include "items/item.hpp" + +#include "config/configmanager.hpp" +#include "creatures/monsters/monster.hpp" +#include "creatures/players/grouping/party.hpp" #include "creatures/players/player.hpp" +#include "game/movement/position.hpp" +#include "items/containers/container.hpp" +#include "items/item.hpp" +#include "lib/di/container.hpp" +#include "utils/tools.hpp" Events::Events() : scriptInterface("Event Interface") { @@ -29,13 +36,13 @@ bool Events::loadFromXml() { info = {}; phmap::flat_hash_set<std::string> classes; - for (auto eventNode : doc.child("events").children()) { + for (const auto &eventNode : doc.child("events").children()) { if (!eventNode.attribute("enabled").as_bool()) { continue; } const std::string &className = eventNode.attribute("class").as_string(); - auto res = classes.emplace(className); + const auto res = classes.emplace(className); if (res.second) { const std::string &lowercase = asLowerCaseString(className); const std::string &scriptName = lowercase + ".lua"; @@ -55,8 +62,6 @@ bool Events::loadFromXml() { info.creatureOnAreaCombat = event; } else if (methodName == "onTargetCombat") { info.creatureOnTargetCombat = event; - } else if (methodName == "onHear") { - info.creatureOnHear = event; } else if (methodName == "onDrainHealth") { info.creatureOnDrainHealth = event; } else { @@ -129,17 +134,9 @@ bool Events::loadFromXml() { } else if (className == "Monster") { if (methodName == "onDropLoot") { info.monsterOnDropLoot = event; - } else if (methodName == "onSpawn") { - info.monsterOnSpawn = event; } else { g_logger().warn("{} - Unknown monster method: {}", __FUNCTION__, methodName); } - } else if (className == "Npc") { - if (methodName == "onSpawn") { - info.monsterOnSpawn = event; - } else { - g_logger().warn("{} - Unknown npc method: {}", __FUNCTION__, methodName); - } } else { g_logger().warn("{} - Unknown class: {}", __FUNCTION__, className); } @@ -147,89 +144,25 @@ bool Events::loadFromXml() { return true; } -// Monster -void Events::eventMonsterOnSpawn(std::shared_ptr<Monster> monster, const Position &position) { - // Monster:onSpawn(position) or Monster.onSpawn(self, position) - if (info.monsterOnSpawn == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - g_logger().error("{} - " - "Position {}" - ". Call stack overflow. Too many lua script calls being nested.", - __FUNCTION__, position.toString()); - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(info.monsterOnSpawn, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(info.monsterOnSpawn); - - LuaScriptInterface::pushUserdata<Monster>(L, monster); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - LuaScriptInterface::pushPosition(L, position); - - if (scriptInterface.protectedCall(L, 2, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); -} - -// Npc -void Events::eventNpcOnSpawn(std::shared_ptr<Npc> npc, const Position &position) { - // Npc:onSpawn(position) or Npc.onSpawn(self, position) - if (info.npcOnSpawn == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - g_logger().error("{} - " - "Position {}" - ". Call stack overflow. Too many lua script calls being nested.", - __FUNCTION__, position.toString()); - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(info.npcOnSpawn, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(info.npcOnSpawn); - - LuaScriptInterface::pushUserdata<Npc>(L, npc); - LuaScriptInterface::setMetatable(L, -1, "Npc"); - LuaScriptInterface::pushPosition(L, position); - - if (scriptInterface.protectedCall(L, 2, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); +Events &Events::getInstance() { + return inject<Events>(); } // Creature -bool Events::eventCreatureOnChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) { +bool Events::eventCreatureOnChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) { // Creature:onChangeOutfit(outfit) or Creature.onChangeOutfit(self, outfit) if (info.creatureOnChangeOutfit == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventCreatureOnChangeOutfit - Creature {}] " "Call stack overflow. Too many lua script calls being nested.", creature->getName()); return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.creatureOnChangeOutfit, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -243,13 +176,13 @@ bool Events::eventCreatureOnChangeOutfit(std::shared_ptr<Creature> creature, con return scriptInterface.callFunction(2); } -ReturnValue Events::eventCreatureOnAreaCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Tile> tile, bool aggressive) { +ReturnValue Events::eventCreatureOnAreaCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile, bool aggressive) { // Creature:onAreaCombat(tile, aggressive) or Creature.onAreaCombat(self, tile, aggressive) if (info.creatureOnAreaCombat == -1) { return RETURNVALUE_NOERROR; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventCreatureOnAreaCombat - " "Creature {} on tile position {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -257,7 +190,7 @@ ReturnValue Events::eventCreatureOnAreaCombat(std::shared_ptr<Creature> creature return RETURNVALUE_NOTPOSSIBLE; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.creatureOnAreaCombat, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -276,7 +209,7 @@ ReturnValue Events::eventCreatureOnAreaCombat(std::shared_ptr<Creature> creature LuaScriptInterface::pushBoolean(L, aggressive); ReturnValue returnValue; - if (scriptInterface.protectedCall(L, 3, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 3, 1) != 0) { returnValue = RETURNVALUE_NOTPOSSIBLE; LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { @@ -284,17 +217,17 @@ ReturnValue Events::eventCreatureOnAreaCombat(std::shared_ptr<Creature> creature lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return returnValue; } -ReturnValue Events::eventCreatureOnTargetCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target) { +ReturnValue Events::eventCreatureOnTargetCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target) { // Creature:onTargetCombat(target) or Creature.onTargetCombat(self, target) if (info.creatureOnTargetCombat == -1) { return RETURNVALUE_NOERROR; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventCreatureOnTargetCombat - " "Creature {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -302,7 +235,7 @@ ReturnValue Events::eventCreatureOnTargetCombat(std::shared_ptr<Creature> creatu return RETURNVALUE_NOTPOSSIBLE; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.creatureOnTargetCombat, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -319,7 +252,7 @@ ReturnValue Events::eventCreatureOnTargetCombat(std::shared_ptr<Creature> creatu LuaScriptInterface::setCreatureMetatable(L, -1, target); ReturnValue returnValue; - if (scriptInterface.protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { returnValue = RETURNVALUE_NOTPOSSIBLE; LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { @@ -327,48 +260,16 @@ ReturnValue Events::eventCreatureOnTargetCombat(std::shared_ptr<Creature> creatu lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); return returnValue; } -void Events::eventCreatureOnHear(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> speaker, const std::string &words, SpeakClasses type) { - // Creature:onHear(speaker, words, type) - if (info.creatureOnHear == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - g_logger().error("[Events::eventCreatureOnHear - " - "Creature {} speaker {}] " - "Call stack overflow. Too many lua script calls being nested.", - creature->getName(), speaker->getName()); - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(info.creatureOnHear, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(info.creatureOnHear); - - LuaScriptInterface::pushUserdata<Creature>(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushUserdata<Creature>(L, speaker); - LuaScriptInterface::setCreatureMetatable(L, -1, speaker); - - LuaScriptInterface::pushString(L, words); - lua_pushnumber(L, type); - - scriptInterface.callVoidFunction(4); -} - -void Events::eventCreatureOnDrainHealth(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) { +void Events::eventCreatureOnDrainHealth(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary) { if (info.creatureOnDrainHealth == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventCreatureOnDrainHealth - " "Creature {} attacker {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -376,7 +277,7 @@ void Events::eventCreatureOnDrainHealth(std::shared_ptr<Creature> creature, std: return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.creatureOnDrainHealth, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -403,7 +304,7 @@ void Events::eventCreatureOnDrainHealth(std::shared_ptr<Creature> creature, std: lua_pushnumber(L, colorPrimary); lua_pushnumber(L, colorSecondary); - if (scriptInterface.protectedCall(L, 8, 6) != 0) { + if (LuaScriptInterface::protectedCall(L, 8, 6) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { typePrimary = LuaScriptInterface::getNumber<CombatType_t>(L, -6); @@ -415,17 +316,17 @@ void Events::eventCreatureOnDrainHealth(std::shared_ptr<Creature> creature, std: lua_pop(L, 6); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } // Party -bool Events::eventPartyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player) { +bool Events::eventPartyOnJoin(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) { // Party:onJoin(player) or Party.onJoin(self, player) if (info.partyOnJoin == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPartyOnJoin - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -433,7 +334,7 @@ bool Events::eventPartyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Play return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.partyOnJoin, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -448,13 +349,13 @@ bool Events::eventPartyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Play return scriptInterface.callFunction(2); } -bool Events::eventPartyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Player> player) { +bool Events::eventPartyOnLeave(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player) { // Party:onLeave(player) or Party.onLeave(self, player) if (info.partyOnLeave == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPartyOnLeave - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -462,7 +363,7 @@ bool Events::eventPartyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Pla return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.partyOnLeave, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -477,20 +378,20 @@ bool Events::eventPartyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Pla return scriptInterface.callFunction(2); } -bool Events::eventPartyOnDisband(std::shared_ptr<Party> party) { +bool Events::eventPartyOnDisband(const std::shared_ptr<Party> &party) { // Party:onDisband() or Party.onDisband(self) if (info.partyOnDisband == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPartyOnDisband - Party leader {}] Call stack " "overflow. Too many lua script calls being nested.", party->getLeader() ? party->getLeader()->getName() : "unknown"); return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.partyOnDisband, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -502,18 +403,18 @@ bool Events::eventPartyOnDisband(std::shared_ptr<Party> party) { return scriptInterface.callFunction(1); } -void Events::eventPartyOnShareExperience(std::shared_ptr<Party> party, uint64_t &exp) { +void Events::eventPartyOnShareExperience(const std::shared_ptr<Party> &party, uint64_t &exp) { // Party:onShareExperience(exp) or Party.onShareExperience(self, exp) if (info.partyOnShareExperience == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("Party leader {}. Call stack overflow. Too many lua script calls being nested.", party->getLeader() ? party->getLeader()->getName() : "unknown"); return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.partyOnShareExperience, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -524,24 +425,24 @@ void Events::eventPartyOnShareExperience(std::shared_ptr<Party> party, uint64_t lua_pushnumber(L, exp); - if (scriptInterface.protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } // Player -bool Events::eventPlayerOnBrowseField(std::shared_ptr<Player> player, const Position &position) { +bool Events::eventPlayerOnBrowseField(const std::shared_ptr<Player> &player, const Position &position) { // Player:onBrowseField(position) or Player.onBrowseField(self, position) if (info.playerOnBrowseField == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnBrowseField - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -549,7 +450,7 @@ bool Events::eventPlayerOnBrowseField(std::shared_ptr<Player> player, const Posi return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnBrowseField, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -563,13 +464,13 @@ bool Events::eventPlayerOnBrowseField(std::shared_ptr<Player> player, const Posi return scriptInterface.callFunction(2); } -void Events::eventPlayerOnLook(std::shared_ptr<Player> player, const Position &position, std::shared_ptr<Thing> thing, uint8_t stackpos, int32_t lookDistance) { +void Events::eventPlayerOnLook(const std::shared_ptr<Player> &player, const Position &position, const std::shared_ptr<Thing> &thing, uint8_t stackpos, int32_t lookDistance) { // Player:onLook(thing, position, distance) or Player.onLook(self, thing, position, distance) if (info.playerOnLook == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnLook - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -577,7 +478,7 @@ void Events::eventPlayerOnLook(std::shared_ptr<Player> player, const Position &p return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnLook, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -586,10 +487,10 @@ void Events::eventPlayerOnLook(std::shared_ptr<Player> player, const Position &p LuaScriptInterface::pushUserdata<Player>(L, player); LuaScriptInterface::setMetatable(L, -1, "Player"); - if (std::shared_ptr<Creature> creature = thing->getCreature()) { + if (const std::shared_ptr<Creature> &creature = thing->getCreature()) { LuaScriptInterface::pushUserdata<Creature>(L, creature); LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else if (std::shared_ptr<Item> item = thing->getItem()) { + } else if (const auto &item = thing->getItem()) { LuaScriptInterface::pushUserdata<Item>(L, item); LuaScriptInterface::setItemMetatable(L, -1, item); } else { @@ -602,13 +503,13 @@ void Events::eventPlayerOnLook(std::shared_ptr<Player> player, const Position &p scriptInterface.callVoidFunction(4); } -void Events::eventPlayerOnLookInBattleList(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, int32_t lookDistance) { +void Events::eventPlayerOnLookInBattleList(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, int32_t lookDistance) { // Player:onLookInBattleList(creature, position, distance) or Player.onLookInBattleList(self, creature, position, distance) if (info.playerOnLookInBattleList == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnLookInBattleList - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -616,7 +517,7 @@ void Events::eventPlayerOnLookInBattleList(std::shared_ptr<Player> player, std:: return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnLookInBattleList, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -633,13 +534,13 @@ void Events::eventPlayerOnLookInBattleList(std::shared_ptr<Player> player, std:: scriptInterface.callVoidFunction(3); } -void Events::eventPlayerOnLookInTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> partner, std::shared_ptr<Item> item, int32_t lookDistance) { +void Events::eventPlayerOnLookInTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &partner, const std::shared_ptr<Item> &item, int32_t lookDistance) { // Player:onLookInTrade(partner, item, distance) or Player.onLookInTrade(self, partner, item, distance) if (info.playerOnLookInTrade == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnLookInTrade - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -647,7 +548,7 @@ void Events::eventPlayerOnLookInTrade(std::shared_ptr<Player> player, std::share return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnLookInTrade, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -667,13 +568,13 @@ void Events::eventPlayerOnLookInTrade(std::shared_ptr<Player> player, std::share scriptInterface.callVoidFunction(4); } -bool Events::eventPlayerOnLookInShop(std::shared_ptr<Player> player, const ItemType* itemType, uint8_t count) { +bool Events::eventPlayerOnLookInShop(const std::shared_ptr<Player> &player, const ItemType* itemType, uint8_t count) { // Player:onLookInShop(itemType, count) or Player.onLookInShop(self, itemType, count) if (info.playerOnLookInShop == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnLookInShop - " "Player {} itemType {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -681,7 +582,7 @@ bool Events::eventPlayerOnLookInShop(std::shared_ptr<Player> player, const ItemT return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnLookInShop, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -698,13 +599,13 @@ bool Events::eventPlayerOnLookInShop(std::shared_ptr<Player> player, const ItemT return scriptInterface.callFunction(3); } -bool Events::eventPlayerOnRemoveCount(std::shared_ptr<Player> player, std::shared_ptr<Item> item) { +bool Events::eventPlayerOnRemoveCount(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item) { // Player:onMove() if (info.playerOnRemoveCount == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnMove - " "Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -712,7 +613,7 @@ bool Events::eventPlayerOnRemoveCount(std::shared_ptr<Player> player, std::share return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnRemoveCount, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -727,13 +628,13 @@ bool Events::eventPlayerOnRemoveCount(std::shared_ptr<Player> player, std::share return scriptInterface.callFunction(2); } -bool Events::eventPlayerOnMoveItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) { +bool Events::eventPlayerOnMoveItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) { // Player:onMoveItem(item, count, fromPosition, toPosition) or Player.onMoveItem(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder) if (info.playerOnMoveItem == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnMoveItem - " "Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -741,7 +642,7 @@ bool Events::eventPlayerOnMoveItem(std::shared_ptr<Player> player, std::shared_p return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnMoveItem, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -763,13 +664,13 @@ bool Events::eventPlayerOnMoveItem(std::shared_ptr<Player> player, std::shared_p return scriptInterface.callFunction(7); } -void Events::eventPlayerOnItemMoved(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder) { +void Events::eventPlayerOnItemMoved(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder) { // Player:onItemMoved(item, count, fromPosition, toPosition) or Player.onItemMoved(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder) if (info.playerOnItemMoved == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnItemMoved - " "Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -777,7 +678,7 @@ void Events::eventPlayerOnItemMoved(std::shared_ptr<Player> player, std::shared_ return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnItemMoved, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -799,13 +700,13 @@ void Events::eventPlayerOnItemMoved(std::shared_ptr<Player> player, std::shared_ scriptInterface.callVoidFunction(7); } -void Events::eventPlayerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t zone) { +void Events::eventPlayerOnChangeZone(const std::shared_ptr<Player> &player, ZoneType_t zone) { // Player:onChangeZone(zone) if (info.playerOnChangeZone == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnChangeZone - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -813,7 +714,7 @@ void Events::eventPlayerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnChangeZone, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -826,13 +727,13 @@ void Events::eventPlayerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t scriptInterface.callVoidFunction(2); } -bool Events::eventPlayerOnMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, const Position &fromPosition, const Position &toPosition) { +bool Events::eventPlayerOnMoveCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, const Position &fromPosition, const Position &toPosition) { // Player:onMoveCreature(creature, fromPosition, toPosition) or Player.onMoveCreature(self, creature, fromPosition, toPosition) if (info.playerOnMoveCreature == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnMoveCreature - " "Player {} creature {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -840,7 +741,7 @@ bool Events::eventPlayerOnMoveCreature(std::shared_ptr<Player> player, std::shar return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnMoveCreature, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -858,13 +759,13 @@ bool Events::eventPlayerOnMoveCreature(std::shared_ptr<Player> player, std::shar return scriptInterface.callFunction(4); } -void Events::eventPlayerOnReportRuleViolation(std::shared_ptr<Player> player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) { +void Events::eventPlayerOnReportRuleViolation(const std::shared_ptr<Player> &player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation) { // Player:onReportRuleViolation(targetName, reportType, reportReason, comment, translation) if (info.playerOnReportRuleViolation == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnReportRuleViolation - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -872,7 +773,7 @@ void Events::eventPlayerOnReportRuleViolation(std::shared_ptr<Player> player, co return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnReportRuleViolation, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -892,13 +793,13 @@ void Events::eventPlayerOnReportRuleViolation(std::shared_ptr<Player> player, co scriptInterface.callVoidFunction(6); } -bool Events::eventPlayerOnReportBug(std::shared_ptr<Player> player, const std::string &message, const Position &position, uint8_t category) { +bool Events::eventPlayerOnReportBug(const std::shared_ptr<Player> &player, const std::string &message, const Position &position, uint8_t category) { // Player:onReportBug(message, position, category) if (info.playerOnReportBug == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnReportBug - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -906,7 +807,7 @@ bool Events::eventPlayerOnReportBug(std::shared_ptr<Player> player, const std::s return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnReportBug, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -922,13 +823,13 @@ bool Events::eventPlayerOnReportBug(std::shared_ptr<Player> player, const std::s return scriptInterface.callFunction(4); } -bool Events::eventPlayerOnTurn(std::shared_ptr<Player> player, Direction direction) { +bool Events::eventPlayerOnTurn(const std::shared_ptr<Player> &player, Direction direction) { // Player:onTurn(direction) or Player.onTurn(self, direction) if (info.playerOnTurn == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnTurn - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -936,7 +837,7 @@ bool Events::eventPlayerOnTurn(std::shared_ptr<Player> player, Direction directi return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnTurn, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -950,13 +851,13 @@ bool Events::eventPlayerOnTurn(std::shared_ptr<Player> player, Direction directi return scriptInterface.callFunction(2); } -bool Events::eventPlayerOnTradeRequest(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item) { +bool Events::eventPlayerOnTradeRequest(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item) { // Player:onTradeRequest(target, item) if (info.playerOnTradeRequest == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnTradeRequest - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -964,7 +865,7 @@ bool Events::eventPlayerOnTradeRequest(std::shared_ptr<Player> player, std::shar return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnTradeRequest, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -982,13 +883,13 @@ bool Events::eventPlayerOnTradeRequest(std::shared_ptr<Player> player, std::shar return scriptInterface.callFunction(3); } -bool Events::eventPlayerOnTradeAccept(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item, std::shared_ptr<Item> targetItem) { +bool Events::eventPlayerOnTradeAccept(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &targetItem) { // Player:onTradeAccept(target, item, targetItem) if (info.playerOnTradeAccept == -1) { return true; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnTradeAccept - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -996,7 +897,7 @@ bool Events::eventPlayerOnTradeAccept(std::shared_ptr<Player> player, std::share return false; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnTradeAccept, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1017,14 +918,14 @@ bool Events::eventPlayerOnTradeAccept(std::shared_ptr<Player> player, std::share return scriptInterface.callFunction(4); } -void Events::eventPlayerOnGainExperience(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint64_t &exp, uint64_t rawExp) { +void Events::eventPlayerOnGainExperience(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint64_t &exp, uint64_t rawExp) { // Player:onGainExperience(target, exp, rawExp) // rawExp gives the original exp which is not multiplied if (info.playerOnGainExperience == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnGainExperience - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1032,7 +933,7 @@ void Events::eventPlayerOnGainExperience(std::shared_ptr<Player> player, std::sh return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnGainExperience, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1051,23 +952,23 @@ void Events::eventPlayerOnGainExperience(std::shared_ptr<Player> player, std::sh lua_pushnumber(L, exp); lua_pushnumber(L, rawExp); - if (scriptInterface.protectedCall(L, 4, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 4, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void Events::eventPlayerOnLoseExperience(std::shared_ptr<Player> player, uint64_t &exp) { +void Events::eventPlayerOnLoseExperience(const std::shared_ptr<Player> &player, uint64_t &exp) { // Player:onLoseExperience(exp) if (info.playerOnLoseExperience == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnLoseExperience - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1075,7 +976,7 @@ void Events::eventPlayerOnLoseExperience(std::shared_ptr<Player> player, uint64_ return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnLoseExperience, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1086,23 +987,23 @@ void Events::eventPlayerOnLoseExperience(std::shared_ptr<Player> player, uint64_ lua_pushnumber(L, exp); - if (scriptInterface.protectedCall(L, 2, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 2, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { exp = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void Events::eventPlayerOnGainSkillTries(std::shared_ptr<Player> player, skills_t skill, uint64_t &tries) { +void Events::eventPlayerOnGainSkillTries(const std::shared_ptr<Player> &player, skills_t skill, uint64_t &tries) { // Player:onGainSkillTries(skill, tries) if (info.playerOnGainSkillTries == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnGainSkillTries - " "Player {} skill {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1110,7 +1011,7 @@ void Events::eventPlayerOnGainSkillTries(std::shared_ptr<Player> player, skills_ return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnGainSkillTries, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1122,23 +1023,23 @@ void Events::eventPlayerOnGainSkillTries(std::shared_ptr<Player> player, skills_ lua_pushnumber(L, skill); lua_pushnumber(L, tries); - if (scriptInterface.protectedCall(L, 3, 1) != 0) { + if (LuaScriptInterface::protectedCall(L, 3, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { tries = LuaScriptInterface::getNumber<uint64_t>(L, -1); lua_pop(L, 1); } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void Events::eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage) { +void Events::eventPlayerOnCombat(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, CombatDamage &damage) { // Player:onCombat(target, item, primaryDamage, primaryType, secondaryDamage, secondaryType) if (info.playerOnCombat == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnCombat - " "Player {} target {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1146,7 +1047,7 @@ void Events::eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnCombat, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1171,7 +1072,7 @@ void Events::eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr LuaScriptInterface::pushCombatDamage(L, damage); - if (scriptInterface.protectedCall(L, 8, 4) != 0) { + if (LuaScriptInterface::protectedCall(L, 8, 4) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); } else { damage.primary.value = std::abs(LuaScriptInterface::getNumber<int32_t>(L, -4)); @@ -1186,16 +1087,16 @@ void Events::eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr } } - scriptInterface.resetScriptEnv(); + LuaScriptInterface::resetScriptEnv(); } -void Events::eventPlayerOnRequestQuestLog(std::shared_ptr<Player> player) { +void Events::eventPlayerOnRequestQuestLog(const std::shared_ptr<Player> &player) { // Player:onRequestQuestLog() if (info.playerOnRequestQuestLog == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnRequestQuestLog - " "Player {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1203,7 +1104,7 @@ void Events::eventPlayerOnRequestQuestLog(std::shared_ptr<Player> player) { return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnRequestQuestLog, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1215,13 +1116,13 @@ void Events::eventPlayerOnRequestQuestLog(std::shared_ptr<Player> player) { scriptInterface.callVoidFunction(1); } -void Events::eventPlayerOnRequestQuestLine(std::shared_ptr<Player> player, uint16_t questId) { +void Events::eventPlayerOnRequestQuestLine(const std::shared_ptr<Player> &player, uint16_t questId) { // Player::onRequestQuestLine() if (info.playerOnRequestQuestLine == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventPlayerOnRequestQuestLine - " "Player {} questId {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1229,7 +1130,7 @@ void Events::eventPlayerOnRequestQuestLine(std::shared_ptr<Player> player, uint1 return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnRequestQuestLine, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1243,18 +1144,18 @@ void Events::eventPlayerOnRequestQuestLine(std::shared_ptr<Player> player, uint1 scriptInterface.callVoidFunction(2); } -void Events::eventPlayerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip) { +void Events::eventPlayerOnInventoryUpdate(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool equip) { // Player:onInventoryUpdate(item, slot, equip) if (info.playerOnInventoryUpdate == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[{}] Call stack overflow", __FUNCTION__); return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnInventoryUpdate, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1272,13 +1173,13 @@ void Events::eventPlayerOnInventoryUpdate(std::shared_ptr<Player> player, std::s scriptInterface.callVoidFunction(4); } -void Events::eventOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) { +void Events::eventOnStorageUpdate(const std::shared_ptr<Player> &player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) { // Player::onStorageUpdate(key, value, oldValue, currentTime) if (info.playerOnStorageUpdate == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventOnStorageUpdate - " "Player {} key {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1286,7 +1187,7 @@ void Events::eventOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.playerOnStorageUpdate, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); @@ -1304,13 +1205,13 @@ void Events::eventOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t } // Monster -void Events::eventMonsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse) { +void Events::eventMonsterOnDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse) { // Monster:onDropLoot(corpse) if (info.monsterOnDropLoot == -1) { return; } - if (!scriptInterface.reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[Events::eventMonsterOnDropLoot - " "Monster corpse {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -1318,7 +1219,7 @@ void Events::eventMonsterOnDropLoot(std::shared_ptr<Monster> monster, std::share return; } - ScriptEnvironment* env = scriptInterface.getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(info.monsterOnDropLoot, &scriptInterface); lua_State* L = scriptInterface.getLuaState(); diff --git a/src/lua/creature/events.hpp b/src/lua/creature/events.hpp index 1ec6d4ba81c..59d6b2f20d0 100644 --- a/src/lua/creature/events.hpp +++ b/src/lua/creature/events.hpp @@ -9,14 +9,31 @@ #pragma once -#include "creatures/players/imbuements/imbuements.hpp" #include "lua/scripts/luascript.hpp" -#include "creatures/combat/spells.hpp" +enum ReturnValue : uint16_t; +enum SpeakClasses : uint8_t; +enum TextColor_t : uint8_t; +enum CombatType_t : uint8_t; +enum Direction : uint8_t; +enum skills_t : int8_t; +enum Slots_t : uint8_t; +enum ZoneType_t : uint8_t; +struct Position; +struct Outfit_t; +struct CombatDamage; class Party; class ItemType; -class Tile; class Imbuements; +class Monster; +class Player; +class Item; +class Creature; +class Npc; +class Tile; +class Thing; +class Cylinder; +class Container; class Events { struct EventsInfo { @@ -24,7 +41,6 @@ class Events { int32_t creatureOnChangeOutfit = -1; int32_t creatureOnAreaCombat = -1; int32_t creatureOnTargetCombat = -1; - int32_t creatureOnHear = -1; int32_t creatureOnDrainHealth = -1; // Party @@ -61,10 +77,6 @@ class Events { // Monster int32_t monsterOnDropLoot = -1; - int32_t monsterOnSpawn = -1; - - // Npc - int32_t npcOnSpawn = -1; }; public: @@ -76,54 +88,47 @@ class Events { Events(const Events &) = delete; void operator=(const Events &) = delete; - static Events &getInstance() { - return inject<Events>(); - } + static Events &getInstance(); // Creature - bool eventCreatureOnChangeOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit); - ReturnValue eventCreatureOnAreaCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Tile> tile, bool aggressive); - ReturnValue eventCreatureOnTargetCombat(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> target); - void eventCreatureOnHear(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> speaker, const std::string &words, SpeakClasses type); - void eventCreatureOnDrainHealth(std::shared_ptr<Creature> creature, std::shared_ptr<Creature> attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary); + bool eventCreatureOnChangeOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit); + ReturnValue eventCreatureOnAreaCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile, bool aggressive); + ReturnValue eventCreatureOnTargetCombat(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &target); + void eventCreatureOnDrainHealth(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Creature> &attacker, CombatType_t &typePrimary, int32_t &damagePrimary, CombatType_t &typeSecondary, int32_t &damageSecondary, TextColor_t &colorPrimary, TextColor_t &colorSecondary); // Party - bool eventPartyOnJoin(std::shared_ptr<Party> party, std::shared_ptr<Player> player); - bool eventPartyOnLeave(std::shared_ptr<Party> party, std::shared_ptr<Player> player); - bool eventPartyOnDisband(std::shared_ptr<Party> party); - void eventPartyOnShareExperience(std::shared_ptr<Party> party, uint64_t &exp); + bool eventPartyOnJoin(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player); + bool eventPartyOnLeave(const std::shared_ptr<Party> &party, const std::shared_ptr<Player> &player); + bool eventPartyOnDisband(const std::shared_ptr<Party> &party); + void eventPartyOnShareExperience(const std::shared_ptr<Party> &party, uint64_t &exp); // Player - bool eventPlayerOnBrowseField(std::shared_ptr<Player> player, const Position &position); - void eventPlayerOnLook(std::shared_ptr<Player> player, const Position &position, std::shared_ptr<Thing> thing, uint8_t stackpos, int32_t lookDistance); - void eventPlayerOnLookInBattleList(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, int32_t lookDistance); - void eventPlayerOnLookInTrade(std::shared_ptr<Player> player, std::shared_ptr<Player> partner, std::shared_ptr<Item> item, int32_t lookDistance); - bool eventPlayerOnLookInShop(std::shared_ptr<Player> player, const ItemType* itemType, uint8_t count); - bool eventPlayerOnMoveItem(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder); - void eventPlayerOnItemMoved(std::shared_ptr<Player> player, std::shared_ptr<Item> item, uint16_t count, const Position &fromPosition, const Position &toPosition, std::shared_ptr<Cylinder> fromCylinder, std::shared_ptr<Cylinder> toCylinder); - void eventPlayerOnChangeZone(std::shared_ptr<Player> player, ZoneType_t zone); - bool eventPlayerOnMoveCreature(std::shared_ptr<Player> player, std::shared_ptr<Creature> creature, const Position &fromPosition, const Position &toPosition); - void eventPlayerOnReportRuleViolation(std::shared_ptr<Player> player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation); - bool eventPlayerOnReportBug(std::shared_ptr<Player> player, const std::string &message, const Position &position, uint8_t category); - bool eventPlayerOnTurn(std::shared_ptr<Player> player, Direction direction); - bool eventPlayerOnTradeRequest(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item); - bool eventPlayerOnTradeAccept(std::shared_ptr<Player> player, std::shared_ptr<Player> target, std::shared_ptr<Item> item, std::shared_ptr<Item> targetItem); - void eventPlayerOnGainExperience(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, uint64_t &exp, uint64_t rawExp); - void eventPlayerOnLoseExperience(std::shared_ptr<Player> player, uint64_t &exp); - void eventPlayerOnGainSkillTries(std::shared_ptr<Player> player, skills_t skill, uint64_t &tries); - bool eventPlayerOnRemoveCount(std::shared_ptr<Player> player, std::shared_ptr<Item> item); - void eventPlayerOnRequestQuestLog(std::shared_ptr<Player> player); - void eventPlayerOnRequestQuestLine(std::shared_ptr<Player> player, uint16_t questId); - void eventOnStorageUpdate(std::shared_ptr<Player> player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime); - void eventPlayerOnCombat(std::shared_ptr<Player> player, std::shared_ptr<Creature> target, std::shared_ptr<Item> item, CombatDamage &damage); - void eventPlayerOnInventoryUpdate(std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool equip); - - // Monster - void eventMonsterOnDropLoot(std::shared_ptr<Monster> monster, std::shared_ptr<Container> corpse); - void eventMonsterOnSpawn(std::shared_ptr<Monster> monster, const Position &position); + bool eventPlayerOnBrowseField(const std::shared_ptr<Player> &player, const Position &position); + void eventPlayerOnLook(const std::shared_ptr<Player> &player, const Position &position, const std::shared_ptr<Thing> &thing, uint8_t stackpos, int32_t lookDistance); + void eventPlayerOnLookInBattleList(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, int32_t lookDistance); + void eventPlayerOnLookInTrade(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &partner, const std::shared_ptr<Item> &item, int32_t lookDistance); + bool eventPlayerOnLookInShop(const std::shared_ptr<Player> &player, const ItemType* itemType, uint8_t count); + bool eventPlayerOnMoveItem(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder); + void eventPlayerOnItemMoved(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, uint16_t count, const Position &fromPosition, const Position &toPosition, const std::shared_ptr<Cylinder> &fromCylinder, const std::shared_ptr<Cylinder> &toCylinder); + void eventPlayerOnChangeZone(const std::shared_ptr<Player> &player, ZoneType_t zone); + bool eventPlayerOnMoveCreature(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &creature, const Position &fromPosition, const Position &toPosition); + void eventPlayerOnReportRuleViolation(const std::shared_ptr<Player> &player, const std::string &targetName, uint8_t reportType, uint8_t reportReason, const std::string &comment, const std::string &translation); + bool eventPlayerOnReportBug(const std::shared_ptr<Player> &player, const std::string &message, const Position &position, uint8_t category); + bool eventPlayerOnTurn(const std::shared_ptr<Player> &player, Direction direction); + bool eventPlayerOnTradeRequest(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item); + bool eventPlayerOnTradeAccept(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target, const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &targetItem); + void eventPlayerOnGainExperience(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, uint64_t &exp, uint64_t rawExp); + void eventPlayerOnLoseExperience(const std::shared_ptr<Player> &player, uint64_t &exp); + void eventPlayerOnGainSkillTries(const std::shared_ptr<Player> &player, skills_t skill, uint64_t &tries); + bool eventPlayerOnRemoveCount(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item); + void eventPlayerOnRequestQuestLog(const std::shared_ptr<Player> &player); + void eventPlayerOnRequestQuestLine(const std::shared_ptr<Player> &player, uint16_t questId); + void eventOnStorageUpdate(const std::shared_ptr<Player> &player, uint32_t key, int32_t value, int32_t oldValue, uint64_t currentTime); + void eventPlayerOnCombat(const std::shared_ptr<Player> &player, const std::shared_ptr<Creature> &target, const std::shared_ptr<Item> &item, CombatDamage &damage); + void eventPlayerOnInventoryUpdate(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool equip); // Monster - void eventNpcOnSpawn(std::shared_ptr<Npc> npc, const Position &position); + void eventMonsterOnDropLoot(const std::shared_ptr<Monster> &monster, const std::shared_ptr<Container> &corpse); private: LuaScriptInterface scriptInterface; diff --git a/src/lua/creature/movement.cpp b/src/lua/creature/movement.cpp index 64e290d8990..6804cdfa7e9 100644 --- a/src/lua/creature/movement.cpp +++ b/src/lua/creature/movement.cpp @@ -7,45 +7,33 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/creature/movement.hpp" + +#include "lib/di/container.hpp" +#include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "lua/creature/events.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" -#include "lua/creature/movement.hpp" - -void MoveEvents::clear(bool isFromXML /*= false*/) { - if (isFromXML) { - int numRemoved = 0; - for (auto &pair : itemIdMap) { - MoveEventList &moveEventList = pair.second; - - for (int moveEventType = 0; moveEventType < MOVE_EVENT_LAST; ++moveEventType) { - auto &eventList = moveEventList.moveEvent[moveEventType]; - - eventList.remove_if([&](const std::shared_ptr<MoveEvent> &moveEvent) { - bool removed = moveEvent && moveEvent->isFromXML(); - if (removed) { - g_logger().debug("MoveEvent with id '{}' is from XML and will be removed.", pair.first); - ++numRemoved; - } - return removed; - }); - } - } +#include "lua/creature/events.hpp" +#include "lua/scripts/scripts.hpp" +#include "creatures/players/vocations/vocation.hpp" +#include "items/item.hpp" +#include "lua/functions/events/move_event_functions.hpp" - if (numRemoved > 0) { - g_logger().debug("Removed '{}' MoveEvent from XML.", numRemoved); - } - return; - } +MoveEvents &MoveEvents::getInstance() { + return inject<MoveEvents>(); +} +void MoveEvents::clear() { uniqueIdMap.clear(); actionIdMap.clear(); itemIdMap.clear(); positionsMap.clear(); } -bool MoveEvents::registerLuaItemEvent(const std::shared_ptr<MoveEvent> moveEvent) { +bool MoveEvents::registerLuaItemEvent(const std::shared_ptr<MoveEvent> &moveEvent) { auto itemIdVector = moveEvent->getItemIdsVector(); if (itemIdVector.empty()) { return false; @@ -71,7 +59,7 @@ bool MoveEvents::registerLuaItemEvent(const std::shared_ptr<MoveEvent> moveEvent return !itemIdVector.empty(); } -bool MoveEvents::registerLuaActionEvent(const std::shared_ptr<MoveEvent> moveEvent) { +bool MoveEvents::registerLuaActionEvent(const std::shared_ptr<MoveEvent> &moveEvent) { auto actionIdVector = moveEvent->getActionIdsVector(); if (actionIdVector.empty()) { return false; @@ -90,7 +78,7 @@ bool MoveEvents::registerLuaActionEvent(const std::shared_ptr<MoveEvent> moveEve return !actionIdVector.empty(); } -bool MoveEvents::registerLuaUniqueEvent(const std::shared_ptr<MoveEvent> moveEvent) { +bool MoveEvents::registerLuaUniqueEvent(const std::shared_ptr<MoveEvent> &moveEvent) { auto uniqueIdVector = moveEvent->getUniqueIdsVector(); if (uniqueIdVector.empty()) { return false; @@ -109,7 +97,7 @@ bool MoveEvents::registerLuaUniqueEvent(const std::shared_ptr<MoveEvent> moveEve return !uniqueIdVector.empty(); } -bool MoveEvents::registerLuaPositionEvent(const std::shared_ptr<MoveEvent> moveEvent) { +bool MoveEvents::registerLuaPositionEvent(const std::shared_ptr<MoveEvent> &moveEvent) { auto positionVector = moveEvent->getPositionsVector(); if (positionVector.empty()) { return false; @@ -128,7 +116,7 @@ bool MoveEvents::registerLuaPositionEvent(const std::shared_ptr<MoveEvent> moveE return !positionVector.empty(); } -bool MoveEvents::registerLuaEvent(const std::shared_ptr<MoveEvent> moveEvent) { +bool MoveEvents::registerLuaEvent(const std::shared_ptr<MoveEvent> &moveEvent) { // Check if event is correct if (registerLuaItemEvent(moveEvent) || registerLuaUniqueEvent(moveEvent) @@ -145,8 +133,8 @@ bool MoveEvents::registerLuaEvent(const std::shared_ptr<MoveEvent> moveEvent) { } } -bool MoveEvents::registerEvent(const std::shared_ptr<MoveEvent> moveEvent, int32_t id, std::map<int32_t, MoveEventList> &moveListMap) const { - auto it = moveListMap.find(id); +bool MoveEvents::registerEvent(const std::shared_ptr<MoveEvent> &moveEvent, int32_t id, std::map<int32_t, MoveEventList> &moveListMap) const { + const auto it = moveListMap.find(id); if (it == moveListMap.end()) { MoveEventList moveEventList; moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); @@ -209,9 +197,9 @@ std::shared_ptr<MoveEvent> MoveEvents::getEvent(const std::shared_ptr<Item> &ite } if (item->hasAttribute(ItemAttribute_t::ACTIONID)) { - std::map<int32_t, MoveEventList>::iterator it = actionIdMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)); + auto it = actionIdMap.find(item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID)); if (it != actionIdMap.end()) { - std::list<std::shared_ptr<MoveEvent>> moveEventList = it->second.moveEvent[eventType]; + const std::list<std::shared_ptr<MoveEvent>> moveEventList = it->second.moveEvent[eventType]; for (const auto &moveEvent : moveEventList) { if ((moveEvent->getSlot() & slotp) != 0) { return moveEvent; @@ -222,7 +210,7 @@ std::shared_ptr<MoveEvent> MoveEvents::getEvent(const std::shared_ptr<Item> &ite auto it = itemIdMap.find(item->getID()); if (it != itemIdMap.end()) { - std::list<std::shared_ptr<MoveEvent>> &moveEventList = it->second.moveEvent[eventType]; + const std::list<std::shared_ptr<MoveEvent>> &moveEventList = it->second.moveEvent[eventType]; for (const auto &moveEvent : moveEventList) { if ((moveEvent->getSlot() & slotp) != 0) { return moveEvent; @@ -264,8 +252,8 @@ std::shared_ptr<MoveEvent> MoveEvents::getEvent(const std::shared_ptr<Item> &ite return nullptr; } -bool MoveEvents::registerEvent(const std::shared_ptr<MoveEvent> moveEvent, const Position &position, std::map<Position, MoveEventList> &moveListMap) const { - auto it = moveListMap.find(position); +bool MoveEvents::registerEvent(const std::shared_ptr<MoveEvent> &moveEvent, const Position &position, std::map<Position, MoveEventList> &moveListMap) const { + const auto it = moveListMap.find(position); if (it == moveListMap.end()) { MoveEventList moveEventList; moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); @@ -289,7 +277,7 @@ bool MoveEvents::registerEvent(const std::shared_ptr<MoveEvent> moveEvent, const } std::shared_ptr<MoveEvent> MoveEvents::getEvent(const std::shared_ptr<Tile> &tile, MoveEvent_t eventType) { - if (auto it = positionsMap.find(tile->getPosition()); + if (const auto it = positionsMap.find(tile->getPosition()); it != positionsMap.end()) { std::list<std::shared_ptr<MoveEvent>> &moveEventList = it->second.moveEvent[eventType]; if (!moveEventList.empty()) { @@ -310,19 +298,19 @@ uint32_t MoveEvents::onCreatureMove(const std::shared_ptr<Creature> &creature, c } for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) { - std::shared_ptr<Thing> thing = tile->getThing(i); + const auto &thing = tile->getThing(i); if (!thing) { continue; } - std::shared_ptr<Item> tileItem = thing->getItem(); + const auto &tileItem = thing->getItem(); if (!tileItem) { continue; } moveEvent = getEvent(tileItem, eventType); if (moveEvent) { - auto step = moveEvent->fireStepEvent(creature, tileItem, pos); + const auto step = moveEvent->fireStepEvent(creature, tileItem, pos); // If there is any problem in the function, we will kill the loop if (step == 0) { break; @@ -334,7 +322,7 @@ uint32_t MoveEvents::onCreatureMove(const std::shared_ptr<Creature> &creature, c } uint32_t MoveEvents::onPlayerEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool isCheck) { - const auto moveEvent = getEvent(item, MOVE_EVENT_EQUIP, slot); + const auto &moveEvent = getEvent(item, MOVE_EVENT_EQUIP, slot); if (!moveEvent) { return 1; } @@ -344,7 +332,7 @@ uint32_t MoveEvents::onPlayerEquip(const std::shared_ptr<Player> &player, const } uint32_t MoveEvents::onPlayerDeEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot) { - const auto moveEvent = getEvent(item, MOVE_EVENT_DEEQUIP, slot); + const auto &moveEvent = getEvent(item, MOVE_EVENT_DEEQUIP, slot); if (!moveEvent) { return 1; } @@ -377,19 +365,19 @@ uint32_t MoveEvents::onItemMove(const std::shared_ptr<Item> &item, const std::sh } for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) { - std::shared_ptr<Thing> thing = tile->getThing(i); + const auto &thing = tile->getThing(i); if (!thing) { continue; } - std::shared_ptr<Item> tileItem = thing->getItem(); + const auto &tileItem = thing->getItem(); if (!tileItem) { continue; } moveEvent = getEvent(tileItem, eventType2); if (moveEvent) { - auto moveItem = moveEvent->fireAddRemItem(item, tileItem, tile->getPosition()); + const auto &moveItem = moveEvent->fireAddRemItem(item, tileItem, tile->getPosition()); // If there is any problem in the function, we will kill the loop if (moveItem == 0) { break; @@ -405,8 +393,8 @@ uint32_t MoveEvents::onItemMove(const std::shared_ptr<Item> &item, const std::sh MoveEvent class ================ */ -MoveEvent::MoveEvent(LuaScriptInterface* interface) : - Script(interface) { } + +MoveEvent::MoveEvent() = default; std::string MoveEvent::getScriptTypeName() const { switch (eventType) { @@ -428,11 +416,38 @@ std::string MoveEvent::getScriptTypeName() const { __FUNCTION__, getScriptInterface()->getLoadingScriptName() ); - return std::string(); + return {}; + } +} + +LuaScriptInterface* MoveEvent::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool MoveEvent::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; } + + return true; +} + +int32_t MoveEvent::getScriptId() const { + return m_scriptId; +} + +void MoveEvent::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; } -uint32_t MoveEvent::StepInField(std::shared_ptr<Creature> creature, std::shared_ptr<Item> item, const Position &) { +bool MoveEvent::isLoadedScriptId() const { + return m_scriptId != 0; +} + +uint32_t MoveEvent::StepInField(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &) { if (creature == nullptr) { g_logger().error("[MoveEvent::StepInField] - Creature is nullptr"); return 0; @@ -443,7 +458,7 @@ uint32_t MoveEvent::StepInField(std::shared_ptr<Creature> creature, std::shared_ return 0; } - std::shared_ptr<MagicField> field = item->getMagicField(); + const auto &field = item->getMagicField(); if (field) { field->onStepInField(creature); return 1; @@ -452,18 +467,18 @@ uint32_t MoveEvent::StepInField(std::shared_ptr<Creature> creature, std::shared_ return LUA_ERROR_ITEM_NOT_FOUND; } -uint32_t MoveEvent::StepOutField(std::shared_ptr<Creature>, std::shared_ptr<Item>, const Position &) { +uint32_t MoveEvent::StepOutField(const std::shared_ptr<Creature> &, const std::shared_ptr<Item> &, const Position &) { return 1; } -uint32_t MoveEvent::AddItemField(std::shared_ptr<Item> item, std::shared_ptr<Item>, const Position &) { +uint32_t MoveEvent::AddItemField(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &, const Position &) { if (item == nullptr) { g_logger().error("[MoveEvent::AddItemField] - Item is nullptr"); return 0; } - if (std::shared_ptr<MagicField> field = item->getMagicField()) { - std::shared_ptr<Tile> tile = item->getTile(); + if (const auto &field = item->getMagicField()) { + const auto &tile = item->getTile(); if (tile == nullptr) { g_logger().debug("[MoveEvent::AddItemField] - Tile is nullptr"); return 0; @@ -486,11 +501,11 @@ uint32_t MoveEvent::AddItemField(std::shared_ptr<Item> item, std::shared_ptr<Ite return LUA_ERROR_ITEM_NOT_FOUND; } -uint32_t MoveEvent::RemoveItemField(std::shared_ptr<Item>, std::shared_ptr<Item>, const Position &) { +uint32_t MoveEvent::RemoveItemField(const std::shared_ptr<Item> &, const std::shared_ptr<Item> &, const Position &) { return 1; } -uint32_t MoveEvent::EquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool isCheck) { +uint32_t MoveEvent::EquipItem(const std::shared_ptr<MoveEvent> &moveEvent, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool isCheck) { if (player == nullptr) { g_logger().error("[MoveEvent::EquipItem] - Player is nullptr"); return 0; @@ -544,12 +559,12 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::s if (it.abilities) { if (it.abilities->invisible) { - std::shared_ptr<Condition> condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_INVISIBLE, -1, 0); + const auto &condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_INVISIBLE, -1, 0); player->addCondition(condition); } if (it.abilities->manaShield) { - std::shared_ptr<Condition> condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_MANASHIELD, -1, 0); + const auto &condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_MANASHIELD, -1, 0); player->addCondition(condition); } @@ -561,7 +576,7 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::s player->sendIcons(); if (it.abilities->regeneration) { - std::shared_ptr<Condition> condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_REGENERATION, -1, 0); + const auto &condition = Condition::createCondition(static_cast<ConditionId_t>(slot), CONDITION_REGENERATION, -1, 0); if (it.abilities->getHealthGain() != 0) { condition->setParam(CONDITION_PARAM_HEALTHGAIN, it.abilities->getHealthGain()); @@ -611,7 +626,7 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::s return 1; } -uint32_t MoveEvent::DeEquipItem(const std::shared_ptr<MoveEvent> MoveEvent, std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool) { +uint32_t MoveEvent::DeEquipItem(const std::shared_ptr<MoveEvent> &, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool) { if (player == nullptr) { g_logger().error("[MoveEvent::EquipItem] - Player is nullptr"); return 0; @@ -696,22 +711,22 @@ void MoveEvent::setEventType(MoveEvent_t type) { eventType = type; } -uint32_t MoveEvent::fireStepEvent(const std::shared_ptr<Creature> &creature, std::shared_ptr<Item> item, const Position &pos) const { - if (isLoadedCallback()) { +uint32_t MoveEvent::fireStepEvent(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos) const { + if (isLoadedScriptId()) { return executeStep(creature, item, pos); } else { return stepFunction(creature, item, pos); } } -bool MoveEvent::executeStep(const std::shared_ptr<Creature> &creature, std::shared_ptr<Item> item, const Position &pos) const { +bool MoveEvent::executeStep(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos) const { // onStepIn(creature, item, pos, fromPosition) // onStepOut(creature, item, pos, fromPosition) // Check if the new position is the same as the old one // If it is, log a warning and either teleport the player to their temple position if item type is an teleport - auto fromPosition = creature->getLastPosition(); - if (auto player = creature->getPlayer(); item && fromPosition == pos && getEventType() == MOVE_EVENT_STEP_IN) { + const auto fromPosition = creature->getLastPosition(); + if (const auto &player = creature->getPlayer(); item && fromPosition == pos && getEventType() == MOVE_EVENT_STEP_IN) { if (const ItemType &itemType = Item::items[item->getID()]; player && itemType.isTeleport()) { g_logger().warn("[{}] cannot teleport player: {}, to the same position: {} of fromPosition: {}", __FUNCTION__, player->getName(), pos.toString(), fromPosition.toString()); g_game().internalTeleport(player, player->getTemplePosition()); @@ -722,7 +737,7 @@ bool MoveEvent::executeStep(const std::shared_ptr<Creature> &creature, std::shar return false; } - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { if (item != nullptr) { g_logger().error("[MoveEvent::executeStep - Creature {} item {}, position {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -735,23 +750,24 @@ bool MoveEvent::executeStep(const std::shared_ptr<Creature> &creature, std::shar return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); - env->setScriptId(getScriptId(), getScriptInterface()); + const auto scriptInterface = getScriptInterface(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); + env->setScriptId(getScriptId(), scriptInterface); - lua_State* L = getScriptInterface()->getLuaState(); + lua_State* L = scriptInterface->getLuaState(); - getScriptInterface()->pushFunction(getScriptId()); + scriptInterface->pushFunction(getScriptId()); LuaScriptInterface::pushUserdata<Creature>(L, creature); LuaScriptInterface::setCreatureMetatable(L, -1, creature); LuaScriptInterface::pushThing(L, item); LuaScriptInterface::pushPosition(L, pos); LuaScriptInterface::pushPosition(L, fromPosition); - return getScriptInterface()->callFunction(4); + return scriptInterface->callFunction(4); } uint32_t MoveEvent::fireEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t toSlot, bool isCheck) { - if (isLoadedCallback()) { + if (isLoadedScriptId()) { if (!equipFunction || equipFunction(static_self_cast<MoveEvent>(), player, item, toSlot, isCheck) == 1) { if (executeEquip(player, item, toSlot, isCheck)) { return 1; @@ -766,14 +782,14 @@ uint32_t MoveEvent::fireEquip(const std::shared_ptr<Player> &player, const std:: bool MoveEvent::executeEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t onSlot, bool isCheck) const { // onEquip(player, item, slot, isCheck) // onDeEquip(player, item, slot, isCheck) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[MoveEvent::executeEquip - Player {} item {}] " "Call stack overflow. Too many lua script calls being nested.", player->getName(), item->getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -789,7 +805,7 @@ bool MoveEvent::executeEquip(const std::shared_ptr<Player> &player, const std::s } uint32_t MoveEvent::fireAddRemItem(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &fromTile, const Position &pos) const { - if (isLoadedCallback()) { + if (isLoadedScriptId()) { return executeAddRemItem(item, fromTile, pos); } else { return moveFunction(item, fromTile, pos); @@ -799,7 +815,7 @@ uint32_t MoveEvent::fireAddRemItem(const std::shared_ptr<Item> &item, const std: bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &fromTile, const Position &pos) const { // onAddItem(moveitem, tileitem, pos) // onRemoveItem(moveitem, tileitem, pos) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[MoveEvent::executeAddRemItem - " "Item {} item on tile x: {} y: {} z: {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -807,7 +823,7 @@ bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const std:: return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -821,7 +837,7 @@ bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const std:: } uint32_t MoveEvent::fireAddRemItem(const std::shared_ptr<Item> &item, const Position &pos) const { - if (isLoadedCallback()) { + if (isLoadedScriptId()) { return executeAddRemItem(item, pos); } else { return moveFunction(item, nullptr, pos); @@ -831,7 +847,7 @@ uint32_t MoveEvent::fireAddRemItem(const std::shared_ptr<Item> &item, const Posi bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const Position &pos) const { // onaddItem(moveitem, pos) // onRemoveItem(moveitem, pos) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[MoveEvent::executeAddRemItem - " "Item {} item on tile x: {} y: {} z: {}] " "Call stack overflow. Too many lua script calls being nested.", @@ -839,7 +855,7 @@ bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const Posit return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -850,3 +866,8 @@ bool MoveEvent::executeAddRemItem(const std::shared_ptr<Item> &item, const Posit return getScriptInterface()->callFunction(2); } + +void MoveEvent::addVocEquipMap(const std::string &vocName) { + const uint16_t vocationId = g_vocations().getVocationId(vocName); + vocEquipMap[vocationId] = true; +} diff --git a/src/lua/creature/movement.hpp b/src/lua/creature/movement.hpp index b8168f58521..bb4554b94d2 100644 --- a/src/lua/creature/movement.hpp +++ b/src/lua/creature/movement.hpp @@ -10,12 +10,13 @@ #pragma once #include "declarations.hpp" -#include "items/item.hpp" -#include "lua/functions/events/move_event_functions.hpp" -#include "lua/scripts/scripts.hpp" -#include "creatures/players/vocations/vocation.hpp" class MoveEvent; +class LuaScriptInterface; +class Item; +class Tile; +class Creature; +class Player; struct MoveEventList { std::list<std::shared_ptr<MoveEvent>> moveEvent[MOVE_EVENT_LAST]; @@ -23,7 +24,7 @@ struct MoveEventList { using VocEquipMap = std::map<uint16_t, bool>; -class MoveEvents final : public Scripts { +class MoveEvents { public: MoveEvents() = default; ~MoveEvents() = default; @@ -32,9 +33,7 @@ class MoveEvents final : public Scripts { MoveEvents(const MoveEvents &) = delete; MoveEvents &operator=(const MoveEvents &) = delete; - static MoveEvents &getInstance() { - return inject<MoveEvents>(); - } + static MoveEvents &getInstance(); uint32_t onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile, MoveEvent_t eventType); uint32_t onPlayerEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool isCheck); @@ -46,7 +45,7 @@ class MoveEvents final : public Scripts { } bool hasPosition(Position position) const { - if (auto it = positionsMap.find(position); + if (const auto it = positionsMap.find(position); it != positionsMap.end()) { return true; } @@ -62,7 +61,7 @@ class MoveEvents final : public Scripts { } bool hasItemId(int32_t itemId) const { - if (auto it = itemIdMap.find(itemId); + if (const auto it = itemIdMap.find(itemId); it != itemIdMap.end()) { return true; } @@ -78,7 +77,7 @@ class MoveEvents final : public Scripts { } bool hasUniqueId(int32_t uniqueId) const { - if (auto it = uniqueIdMap.find(uniqueId); + if (const auto it = uniqueIdMap.find(uniqueId); it != uniqueIdMap.end()) { return true; } @@ -94,7 +93,7 @@ class MoveEvents final : public Scripts { } bool hasActionId(int32_t actionId) const { - if (auto it = actionIdMap.find(actionId); + if (const auto it = actionIdMap.find(actionId); it != actionIdMap.end()) { return true; } @@ -107,19 +106,16 @@ class MoveEvents final : public Scripts { std::shared_ptr<MoveEvent> getEvent(const std::shared_ptr<Item> &item, MoveEvent_t eventType); - bool registerLuaItemEvent(const std::shared_ptr<MoveEvent> moveEvent); - bool registerLuaActionEvent(const std::shared_ptr<MoveEvent> moveEvent); - bool registerLuaUniqueEvent(const std::shared_ptr<MoveEvent> moveEvent); - bool registerLuaPositionEvent(const std::shared_ptr<MoveEvent> moveEvent); - bool registerLuaEvent(const std::shared_ptr<MoveEvent> event); - void clear(bool isFromXML = false); + bool registerLuaItemEvent(const std::shared_ptr<MoveEvent> &moveEvent); + bool registerLuaActionEvent(const std::shared_ptr<MoveEvent> &moveEvent); + bool registerLuaUniqueEvent(const std::shared_ptr<MoveEvent> &moveEvent); + bool registerLuaPositionEvent(const std::shared_ptr<MoveEvent> &moveEvent); + bool registerLuaEvent(const std::shared_ptr<MoveEvent> &event); + void clear(); private: - void clearMap(std::map<int32_t, MoveEventList> &map) const; - void clearPosMap(std::map<Position, MoveEventList> &map); - - bool registerEvent(const std::shared_ptr<MoveEvent> moveEvent, int32_t id, std::map<int32_t, MoveEventList> &moveListMap) const; - bool registerEvent(const std::shared_ptr<MoveEvent> moveEvent, const Position &position, std::map<Position, MoveEventList> &moveListMap) const; + bool registerEvent(const std::shared_ptr<MoveEvent> &moveEvent, int32_t id, std::map<int32_t, MoveEventList> &moveListMap) const; + bool registerEvent(const std::shared_ptr<MoveEvent> &moveEvent, const Position &position, std::map<Position, MoveEventList> &moveListMap) const; std::shared_ptr<MoveEvent> getEvent(const std::shared_ptr<Tile> &tile, MoveEvent_t eventType); std::shared_ptr<MoveEvent> getEvent(const std::shared_ptr<Item> &item, MoveEvent_t eventType, Slots_t slot); @@ -132,14 +128,14 @@ class MoveEvents final : public Scripts { constexpr auto g_moveEvents = MoveEvents::getInstance; -class MoveEvent final : public Script, public SharedObject { +class MoveEvent final : public SharedObject { public: - explicit MoveEvent(LuaScriptInterface* interface); + explicit MoveEvent(); MoveEvent_t getEventType() const; void setEventType(MoveEvent_t type); - uint32_t fireStepEvent(const std::shared_ptr<Creature> &creature, std::shared_ptr<Item> item, const Position &pos) const; + uint32_t fireStepEvent(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos) const; uint32_t fireAddRemItem(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &tileItem, const Position &pos) const; uint32_t fireAddRemItem(const std::shared_ptr<Item> &item, const Position &pos) const; uint32_t fireEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool isCheck); @@ -149,7 +145,7 @@ class MoveEvent final : public Script, public SharedObject { } // Scripting to lua interface - bool executeStep(const std::shared_ptr<Creature> &creature, std::shared_ptr<Item> item, const Position &pos) const; + bool executeStep(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos) const; bool executeEquip(const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool isCheck) const; bool executeAddRemItem(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &tileItem, const Position &pos) const; // No have tile item @@ -178,12 +174,7 @@ class MoveEvent final : public Script, public SharedObject { const std::map<uint16_t, bool> &getVocEquipMap() const { return vocEquipMap; } - void addVocEquipMap(std::string vocName) { - uint16_t vocationId = g_vocations().getVocationId(vocName); - if (vocationId != 65535) { - vocEquipMap[vocationId] = true; - } - } + void addVocEquipMap(const std::string &vocName); bool getTileItem() const { return tileItem; } @@ -217,50 +208,46 @@ class MoveEvent final : public Script, public SharedObject { void setSlot(uint32_t s) { slot = s; } - uint32_t getRequiredLevel() { + uint32_t getRequiredLevel() const { return reqLevel; } void setRequiredLevel(uint32_t level) { reqLevel = level; } - uint32_t getRequiredMagLevel() { + uint32_t getRequiredMagLevel() const { return reqMagLevel; } void setRequiredMagLevel(uint32_t level) { reqMagLevel = level; } - bool needPremium() { + bool needPremium() const { return premium; } void setNeedPremium(bool b) { premium = b; } - uint32_t getWieldInfo() { - return wieldInfo; - } void setWieldInfo(WieldInfo_t info) { wieldInfo |= info; } - static uint32_t StepInField(std::shared_ptr<Creature> creature, std::shared_ptr<Item> item, const Position &pos); - static uint32_t StepOutField(std::shared_ptr<Creature> creature, std::shared_ptr<Item> item, const Position &pos); + static uint32_t StepInField(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos); + static uint32_t StepOutField(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Item> &item, const Position &pos); - static uint32_t AddItemField(std::shared_ptr<Item> item, std::shared_ptr<Item> tileItem, const Position &pos); - static uint32_t RemoveItemField(std::shared_ptr<Item> item, std::shared_ptr<Item> tileItem, const Position &pos); + static uint32_t AddItemField(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &tileItem, const Position &pos); + static uint32_t RemoveItemField(const std::shared_ptr<Item> &item, const std::shared_ptr<Item> &tileItem, const Position &pos); - static uint32_t EquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool boolean); - static uint32_t DeEquipItem(const std::shared_ptr<MoveEvent> moveEvent, std::shared_ptr<Player> player, std::shared_ptr<Item> item, Slots_t slot, bool boolean); + static uint32_t EquipItem(const std::shared_ptr<MoveEvent> &moveEvent, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool boolean); + static uint32_t DeEquipItem(const std::shared_ptr<MoveEvent> &, const std::shared_ptr<Player> &player, const std::shared_ptr<Item> &item, Slots_t slot, bool boolean); - void setFromXML(bool newFromXML) { - m_fromXML = newFromXML; - } - - bool isFromXML() const { - return m_fromXML; - } + std::string getScriptTypeName() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; + LuaScriptInterface* getScriptInterface() const; private: - std::string getScriptTypeName() const override; + int32_t m_scriptId {}; uint32_t slot = SLOTP_WHEREEVER; @@ -282,7 +269,7 @@ class MoveEvent final : public Script, public SharedObject { // equipFunction std::function<uint32_t( std::shared_ptr<MoveEvent> moveEvent, - std::shared_ptr<Player> player, + const std::shared_ptr<Player> &player, std::shared_ptr<Item> item, Slots_t slot, bool boolean @@ -298,8 +285,6 @@ class MoveEvent final : public Script, public SharedObject { std::map<uint16_t, bool> vocEquipMap; bool tileItem = false; - bool m_fromXML = false; - std::vector<uint32_t> itemIdVector; std::vector<uint32_t> actionIdVector; std::vector<uint32_t> uniqueIdVector; diff --git a/src/lua/creature/raids.cpp b/src/lua/creature/raids.cpp index 818ad077e77..2a9a174e6a7 100644 --- a/src/lua/creature/raids.cpp +++ b/src/lua/creature/raids.cpp @@ -8,11 +8,13 @@ */ #include "lua/creature/raids.hpp" -#include "utils/pugicast.hpp" + +#include "config/configmanager.hpp" +#include "creatures/monsters/monster.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" -#include "creatures/monsters/monster.hpp" #include "server/network/webhook/webhook.hpp" +#include "utils/pugicast.hpp" Raids::Raids() { scriptInterface.initState(); @@ -31,7 +33,7 @@ bool Raids::loadFromXml() { return false; } - for (auto raidNode : doc.child("raids").children()) { + for (const auto &raidNode : doc.child("raids").children()) { std::string name, file; uint32_t interval, margin; @@ -113,14 +115,14 @@ void Raids::checkRaids() { return; } if (!getRunning()) { - uint64_t now = OTSYS_TIME(); + const uint64_t now = OTSYS_TIME(); for (auto it = raidList.begin(), end = raidList.end(); it != end; ++it) { const auto &raid = *it; if (now >= (getLastRaidEnd() + raid->getMargin())) { - auto roll = static_cast<uint32_t>(uniform_random(0, MAX_RAND_RANGE)); - auto required = static_cast<uint32_t>(MAX_RAND_RANGE * raid->getInterval()) / CHECK_RAIDS_INTERVAL; - auto shouldStart = required >= roll; + const auto roll = static_cast<uint32_t>(uniform_random(0, MAX_RAND_RANGE)); + const auto required = static_cast<uint32_t>(MAX_RAND_RANGE * raid->getInterval()) / CHECK_RAIDS_INTERVAL; + const auto shouldStart = required >= roll; if (shouldStart) { setRunning(raid); raid->startRaid(); @@ -161,7 +163,7 @@ bool Raids::reload() { return loadFromXml(); } -std::shared_ptr<Raid> Raids::getRaidByName(const std::string &name) { +std::shared_ptr<Raid> Raids::getRaidByName(const std::string &name) const { for (const auto &raid : raidList) { if (strcasecmp(raid->getName().c_str(), name.c_str()) == 0) { return raid; @@ -176,13 +178,13 @@ bool Raid::loadFromXml(const std::string &filename) { } pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); + const pugi::xml_parse_result result = doc.load_file(filename.c_str()); if (!result) { printXMLError(__FUNCTION__, filename, result); return false; } - for (auto eventNode : doc.child("raid").children()) { + for (const auto &eventNode : doc.child("raid").children()) { std::shared_ptr<RaidEvent> event; if (strcasecmp(eventNode.name(), "announce") == 0) { event = std::make_shared<AnnounceEvent>(); @@ -206,7 +208,7 @@ bool Raid::loadFromXml(const std::string &filename) { } // sort by delay time - std::sort(raidEvents.begin(), raidEvents.end(), [](const std::shared_ptr<RaidEvent> lhs, const std::shared_ptr<RaidEvent> rhs) { + std::ranges::sort(raidEvents, [](const std::shared_ptr<RaidEvent> &lhs, const std::shared_ptr<RaidEvent> &rhs) { return lhs->getDelay() < rhs->getDelay(); }); @@ -227,13 +229,13 @@ void Raid::startRaid() { } } -void Raid::executeRaidEvent(const std::shared_ptr<RaidEvent> raidEvent) { +void Raid::executeRaidEvent(const std::shared_ptr<RaidEvent> &raidEvent) { if (raidEvent->executeEvent()) { nextEvent++; const auto newRaidEvent = getNextRaidEvent(); if (newRaidEvent) { - uint32_t ticks = static_cast<uint32_t>(std::max<int32_t>(RAID_MINTICKS, newRaidEvent->getDelay() - raidEvent->getDelay())); + const uint32_t ticks = static_cast<uint32_t>(std::max<int32_t>(RAID_MINTICKS, newRaidEvent->getDelay() - raidEvent->getDelay())); nextEventEvent = g_dispatcher().scheduleEvent( ticks, [this, newRaidEvent] { executeRaidEvent(newRaidEvent); }, __FUNCTION__ ); @@ -268,7 +270,7 @@ std::shared_ptr<RaidEvent> Raid::getNextRaidEvent() { } bool RaidEvent::configureRaidEvent(const pugi::xml_node &eventNode) { - pugi::xml_attribute delayAttribute = eventNode.attribute("delay"); + const pugi::xml_attribute delayAttribute = eventNode.attribute("delay"); if (!delayAttribute) { g_logger().error("{} - 'delay' tag missing", __FUNCTION__); return false; @@ -283,7 +285,7 @@ bool AnnounceEvent::configureRaidEvent(const pugi::xml_node &eventNode) { return false; } - pugi::xml_attribute messageAttribute = eventNode.attribute("message"); + const pugi::xml_attribute messageAttribute = eventNode.attribute("message"); if (!messageAttribute) { g_logger().error("{} - " "'message' tag missing for announce event", @@ -292,9 +294,9 @@ bool AnnounceEvent::configureRaidEvent(const pugi::xml_node &eventNode) { } message = messageAttribute.as_string(); - pugi::xml_attribute typeAttribute = eventNode.attribute("type"); + const pugi::xml_attribute typeAttribute = eventNode.attribute("type"); if (typeAttribute) { - std::string tmpStrValue = asLowerCaseString(typeAttribute.as_string()); + const std::string tmpStrValue = asLowerCaseString(typeAttribute.as_string()); if (tmpStrValue == "warning") { messageType = MESSAGE_GAME_HIGHLIGHT; } else if (tmpStrValue == "event") { @@ -374,7 +376,7 @@ bool SingleSpawnEvent::configureRaidEvent(const pugi::xml_node &eventNode) { } bool SingleSpawnEvent::executeEvent() { - std::shared_ptr<Monster> monster = Monster::createMonster(monsterName); + const auto &monster = Monster::createMonster(monsterName); if (!monster) { g_logger().error("{} - Cant create monster {}", __FUNCTION__, monsterName); return false; @@ -396,7 +398,7 @@ bool AreaSpawnEvent::configureRaidEvent(const pugi::xml_node &eventNode) { pugi::xml_attribute attr; if ((attr = eventNode.attribute("radius"))) { - int32_t radius = pugi::cast<int32_t>(attr.value()); + const auto radius = pugi::cast<int32_t>(attr.value()); Position centerPos; if ((attr = eventNode.attribute("centerx"))) { @@ -490,7 +492,7 @@ bool AreaSpawnEvent::configureRaidEvent(const pugi::xml_node &eventNode) { } } - for (auto monsterNode : eventNode.children()) { + for (const auto &monsterNode : eventNode.children()) { const char* name; if ((attr = monsterNode.attribute("name"))) { @@ -535,26 +537,26 @@ bool AreaSpawnEvent::configureRaidEvent(const pugi::xml_node &eventNode) { bool AreaSpawnEvent::executeEvent() { for (const MonsterSpawn &spawn : spawnMonsterList) { - uint32_t amount = uniform_random(spawn.minAmount, spawn.maxAmount); + const uint32_t amount = uniform_random(spawn.minAmount, spawn.maxAmount); for (uint32_t i = 0; i < amount; ++i) { - std::shared_ptr<Monster> monster = Monster::createMonster(spawn.name); + const std::shared_ptr<Monster> &monster = Monster::createMonster(spawn.name); if (!monster) { g_logger().error("{} - Can't create monster {}", __FUNCTION__, spawn.name); return false; } - bool success = false; for (int32_t tries = 0; tries < MAXIMUM_TRIES_PER_MONSTER; tries++) { - std::shared_ptr<Tile> tile = g_game().map.getTile(static_cast<uint16_t>(uniform_random(fromPos.x, toPos.x)), static_cast<uint16_t>(uniform_random(fromPos.y, toPos.y)), static_cast<uint8_t>(uniform_random(fromPos.z, toPos.z))); - if (tile && !tile->isMovableBlocking() && !tile->hasFlag(TILESTATE_PROTECTIONZONE) && tile->getTopCreature() == nullptr && g_game().placeCreature(monster, tile->getPosition(), false, true)) { - success = true; + const auto &tile = g_game().map.getTile(static_cast<uint16_t>(uniform_random(fromPos.x, toPos.x)), static_cast<uint16_t>(uniform_random(fromPos.y, toPos.y)), static_cast<uint8_t>(uniform_random(fromPos.z, toPos.z))); + if (!tile) { + continue; + } + + const auto &topCreature = tile->getTopCreature(); + if (!tile->isMovableBlocking() && !tile->hasFlag(TILESTATE_PROTECTIONZONE) && topCreature == nullptr && g_game().placeCreature(monster, tile->getPosition(), false, true)) { monster->setForgeMonster(false); break; } } - - if (!success) { - } } } return true; @@ -565,7 +567,7 @@ bool ScriptEvent::configureRaidEvent(const pugi::xml_node &eventNode) { return false; } - pugi::xml_attribute scriptAttribute = eventNode.attribute("script"); + const pugi::xml_attribute scriptAttribute = eventNode.attribute("script"); if (!scriptAttribute) { g_logger().error("{} - " "No script file found for raid", @@ -591,14 +593,14 @@ std::string ScriptEvent::getScriptEventName() const { bool ScriptEvent::executeEvent() { // onRaid() - if (!scriptInterface->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("{} - Script with name {} " "Call stack overflow. Too many lua script calls being nested.", __FUNCTION__, getScriptName()); return false; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(scriptId, scriptInterface); scriptInterface->pushFunction(scriptId); diff --git a/src/lua/creature/raids.hpp b/src/lua/creature/raids.hpp index 0266641edda..d2f45536b4b 100644 --- a/src/lua/creature/raids.hpp +++ b/src/lua/creature/raids.hpp @@ -9,10 +9,11 @@ #pragma once -#include "utils/utils_definitions.hpp" -#include "declarations.hpp" -#include "game/movement/position.hpp" #include "lua/global/baseevents.hpp" +#include "lua/scripts/luascript.hpp" +#include "utils/utils_definitions.hpp" + +struct Position; struct MonsterSpawn { MonsterSpawn(std::string initName, uint32_t initMinAmount, uint32_t initMaxAmount) : @@ -56,11 +57,11 @@ class Raids { std::shared_ptr<Raid> getRunning() { return running; } - void setRunning(const std::shared_ptr<Raid> newRunning) { + void setRunning(const std::shared_ptr<Raid> &newRunning) { running = newRunning; } - std::shared_ptr<Raid> getRaidByName(const std::string &name); + std::shared_ptr<Raid> getRaidByName(const std::string &name) const; uint64_t getLastRaidEnd() const { return lastRaidEnd; @@ -100,7 +101,7 @@ class Raid { void startRaid(); - void executeRaidEvent(const std::shared_ptr<RaidEvent> raidEvent); + void executeRaidEvent(const std::shared_ptr<RaidEvent> &raidEvent); void resetRaid(); std::shared_ptr<RaidEvent> getNextRaidEvent(); @@ -150,7 +151,7 @@ class RaidEvent { } private: - uint32_t delay; + uint32_t delay {}; }; class AnnounceEvent final : public RaidEvent { @@ -202,7 +203,7 @@ class ScriptEvent final : public RaidEvent, public Event { return scriptName; } void setScriptName(std::string name) { - scriptName = name; + scriptName = std::move(name); } bool executeEvent() override; diff --git a/src/lua/creature/talkaction.cpp b/src/lua/creature/talkaction.cpp index 4dbf829d3c5..abe9303a5ba 100644 --- a/src/lua/creature/talkaction.cpp +++ b/src/lua/creature/talkaction.cpp @@ -7,13 +7,21 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/creature/talkaction.hpp" + +#include "utils/tools.hpp" +#include "creatures/players/grouping/groups.hpp" #include "creatures/players/player.hpp" #include "lua/scripts/scripts.hpp" -#include "lua/creature/talkaction.hpp" +#include "lib/di/container.hpp" TalkActions::TalkActions() = default; TalkActions::~TalkActions() = default; +TalkActions &TalkActions::getInstance() { + return inject<TalkActions>(); +} + void TalkActions::clear() { talkActions.clear(); } @@ -23,29 +31,29 @@ bool TalkActions::registerLuaEvent(const TalkAction_ptr &talkAction) { return inserted; } -bool TalkActions::checkWord(std::shared_ptr<Player> player, SpeakClasses type, const std::string &words, std::string_view word, const TalkAction_ptr &talkActionPtr) const { - auto spacePos = std::ranges::find_if(words.begin(), words.end(), ::isspace); - std::string firstWord = words.substr(0, spacePos - words.begin()); +bool TalkActions::checkWord(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &words, std::string_view word, const TalkAction_ptr &talkActionPtr) const { + const auto spacePos = std::ranges::find_if(words.begin(), words.end(), ::isspace); + const std::string firstWord = words.substr(0, spacePos - words.begin()); // Check for exact equality from saying word and talkaction stored word if (firstWord != word) { return false; } - auto groupId = player->getGroup()->id; + const auto groupId = player->getGroup()->id; if (groupId < talkActionPtr->getGroupType()) { return false; } std::string param; - size_t wordPos = words.find(word); - size_t talkactionLength = word.length(); + const size_t wordPos = words.find(word); + const size_t talkactionLength = word.length(); if (wordPos != std::string::npos && wordPos + talkactionLength < words.length()) { param = words.substr(wordPos + talkactionLength); trim_left(param, ' '); } - std::string separator = talkActionPtr->getSeparator(); + const std::string separator = talkActionPtr->getSeparator(); if (separator != " ") { if (!param.empty()) { if (param != separator) { @@ -59,7 +67,7 @@ bool TalkActions::checkWord(std::shared_ptr<Player> player, SpeakClasses type, c return talkActionPtr->executeSay(player, words, param, type); } -TalkActionResult_t TalkActions::checkPlayerCanSayTalkAction(std::shared_ptr<Player> player, SpeakClasses type, const std::string &words) const { +TalkActionResult_t TalkActions::checkPlayerCanSayTalkAction(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &words) const { for (const auto &[talkactionWords, talkActionPtr] : talkActions) { if (talkactionWords.find(',') != std::string::npos) { auto wordsList = split(talkactionWords); @@ -77,16 +85,43 @@ TalkActionResult_t TalkActions::checkPlayerCanSayTalkAction(std::shared_ptr<Play return TALKACTION_CONTINUE; } -bool TalkAction::executeSay(std::shared_ptr<Player> player, const std::string &words, const std::string ¶m, SpeakClasses type) const { +LuaScriptInterface* TalkAction::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool TalkAction::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t TalkAction::getScriptId() const { + return m_scriptId; +} + +void TalkAction::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool TalkAction::isLoadedScriptId() const { + return m_scriptId != 0; +} + +bool TalkAction::executeSay(const std::shared_ptr<Player> &player, const std::string &words, const std::string ¶m, SpeakClasses type) const { // onSay(player, words, param, type) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[TalkAction::executeSay - Player {} words {}] " "Call stack overflow. Too many lua script calls being nested. Script name {}", player->getName(), getWords(), getScriptInterface()->getLoadingScriptName()); return false; } - ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* scriptEnvironment = LuaScriptInterface::getScriptEnv(); scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -98,7 +133,7 @@ bool TalkAction::executeSay(std::shared_ptr<Player> player, const std::string &w LuaScriptInterface::pushString(L, words); LuaScriptInterface::pushString(L, param); - lua_pushnumber(L, type); + LuaScriptInterface::pushNumber(L, static_cast<lua_Number>(type)); return getScriptInterface()->callFunction(4); } diff --git a/src/lua/creature/talkaction.hpp b/src/lua/creature/talkaction.hpp index 50ade58172d..4040a10f873 100644 --- a/src/lua/creature/talkaction.hpp +++ b/src/lua/creature/talkaction.hpp @@ -10,19 +10,16 @@ #pragma once #include "account/account.hpp" -#include "lua/global/baseevents.hpp" #include "utils/utils_definitions.hpp" #include "declarations.hpp" -#include "lua/scripts/luascript.hpp" -#include "lua/scripts/scripts.hpp" +class Player; +class LuaScriptInterface; class TalkAction; using TalkAction_ptr = std::shared_ptr<TalkAction>; -class TalkAction : public Script { +class TalkAction final { public: - using Script::Script; - const std::string &getWords() const { return m_word; } @@ -48,20 +45,24 @@ class TalkAction : public Script { return separator; } void setSeparator(std::string sep) { - separator = sep; + separator = std::move(sep); } // scripting - bool executeSay(std::shared_ptr<Player> player, const std::string &words, const std::string ¶m, SpeakClasses type) const; + bool executeSay(const std::shared_ptr<Player> &player, const std::string &words, const std::string ¶m, SpeakClasses type) const; // void setGroupType(uint8_t newGroupType); const uint8_t &getGroupType() const; + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; + private: - std::string getScriptTypeName() const override { - return "onSay"; - } + int32_t m_scriptId {}; std::string m_word; std::string m_description; @@ -69,7 +70,7 @@ class TalkAction : public Script { uint8_t m_groupType = 0; }; -class TalkActions final : public Scripts { +class TalkActions { public: TalkActions(); ~TalkActions(); @@ -78,12 +79,10 @@ class TalkActions final : public Scripts { TalkActions(const TalkActions &) = delete; TalkActions &operator=(const TalkActions &) = delete; - static TalkActions &getInstance() { - return inject<TalkActions>(); - } + static TalkActions &getInstance(); - bool checkWord(std::shared_ptr<Player> player, SpeakClasses type, const std::string &words, std::string_view word, const TalkAction_ptr &talkActionPtr) const; - TalkActionResult_t checkPlayerCanSayTalkAction(std::shared_ptr<Player> player, SpeakClasses type, const std::string &words) const; + bool checkWord(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &words, std::string_view word, const TalkAction_ptr &talkActionPtr) const; + TalkActionResult_t checkPlayerCanSayTalkAction(const std::shared_ptr<Player> &player, SpeakClasses type, const std::string &words) const; bool registerLuaEvent(const TalkAction_ptr &talkAction); void clear(); diff --git a/src/lua/functions/core/CMakeLists.txt b/src/lua/functions/core/CMakeLists.txt index 1cf919da3ec..e9ac9899a6c 100644 --- a/src/lua/functions/core/CMakeLists.txt +++ b/src/lua/functions/core/CMakeLists.txt @@ -6,7 +6,6 @@ target_sources(${PROJECT_NAME}_lib PRIVATE game/lua_enums.cpp game/modal_window_functions.cpp game/zone_functions.cpp - libs/bit_functions.cpp libs/db_functions.cpp libs/result_functions.cpp libs/logger_functions.cpp diff --git a/src/lua/functions/core/core_functions.hpp b/src/lua/functions/core/core_functions.hpp index c6c14121b06..2a75d148c51 100644 --- a/src/lua/functions/core/core_functions.hpp +++ b/src/lua/functions/core/core_functions.hpp @@ -16,6 +16,12 @@ class CoreFunctions final : LuaScriptInterface { public: + explicit CoreFunctions(lua_State* L) : + LuaScriptInterface("CoreFunctions") { + init(L); + } + ~CoreFunctions() override = default; + static void init(lua_State* L) { CoreGameFunctions::init(L); CoreLibsFunctions::init(L); diff --git a/src/lua/functions/core/game/bank_functions.cpp b/src/lua/functions/core/game/bank_functions.cpp index 26005db41e3..88665337a42 100644 --- a/src/lua/functions/core/game/bank_functions.cpp +++ b/src/lua/functions/core/game/bank_functions.cpp @@ -8,58 +8,73 @@ */ #include "lua/functions/core/game/bank_functions.hpp" + +#include "creatures/players/player.hpp" #include "game/bank/bank.hpp" #include "game/game.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void BankFunctions::init(lua_State* L) { + Lua::registerTable(L, "Bank"); + Lua::registerMethod(L, "Bank", "credit", BankFunctions::luaBankCredit); + Lua::registerMethod(L, "Bank", "debit", BankFunctions::luaBankDebit); + Lua::registerMethod(L, "Bank", "balance", BankFunctions::luaBankBalance); + Lua::registerMethod(L, "Bank", "hasBalance", BankFunctions::luaBankHasBalance); + Lua::registerMethod(L, "Bank", "transfer", BankFunctions::luaBankTransfer); + Lua::registerMethod(L, "Bank", "transferToGuild", BankFunctions::luaBankTransferToGuild); + Lua::registerMethod(L, "Bank", "withdraw", BankFunctions::luaBankWithdraw); + Lua::registerMethod(L, "Bank", "deposit", BankFunctions::luaBankDeposit); +} int BankFunctions::luaBankCredit(lua_State* L) { // Bank.credit(playerOrGuild, amount) - auto bank = getBank(L, 1); + const auto &bank = getBank(L, 1); if (bank == nullptr) { - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } - uint64_t amount = getNumber<uint64_t>(L, 2); - pushBoolean(L, bank->credit(amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 2); + Lua::pushBoolean(L, bank->credit(amount)); return 1; } int BankFunctions::luaBankDebit(lua_State* L) { // Bank.debit(playerOrGuild, amount) - auto bank = getBank(L, 1); + const auto &bank = getBank(L, 1); if (bank == nullptr) { - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } - uint64_t amount = getNumber<uint64_t>(L, 2); - pushBoolean(L, bank->debit(amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 2); + Lua::pushBoolean(L, bank->debit(amount)); return 1; } int BankFunctions::luaBankBalance(lua_State* L) { // Bank.balance(playerOrGuild[, amount]]) - auto bank = getBank(L, 1); + const auto &bank = getBank(L, 1); if (bank == nullptr) { - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, bank->balance()); return 1; } - uint64_t amount = getNumber<uint64_t>(L, 2); - pushBoolean(L, bank->balance(amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 2); + Lua::pushBoolean(L, bank->balance(amount)); return 1; } int BankFunctions::luaBankHasBalance(lua_State* L) { // Bank.hasBalance(playerOrGuild, amount) - auto bank = getBank(L, 1); + const auto &bank = getBank(L, 1); if (bank == nullptr) { - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } - uint64_t amount = getNumber<uint64_t>(L, 2); - pushBoolean(L, bank->hasBalance(amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 2); + Lua::pushBoolean(L, bank->hasBalance(amount)); return 1; } @@ -68,17 +83,17 @@ int BankFunctions::luaBankTransfer(lua_State* L) { const auto &source = getBank(L, 1); if (source == nullptr) { g_logger().debug("BankFunctions::luaBankTransfer: source is null"); - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } const auto &destination = getBank(L, 2); if (destination == nullptr) { g_logger().debug("BankFunctions::luaBankTransfer: destination is null"); - reportErrorFunc("Bank is nullptr"); + Lua::reportErrorFunc("Bank is nullptr"); return 1; } - const uint64_t amount = getNumber<uint64_t>(L, 3); - pushBoolean(L, source->transferTo(destination, amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 3); + Lua::pushBoolean(L, source->transferTo(destination, amount)); return 1; } @@ -86,83 +101,83 @@ int BankFunctions::luaBankTransferToGuild(lua_State* L) { // Bank.transfer(fromPlayerOrGuild, toGuild, amount) const auto &source = getBank(L, 1); if (source == nullptr) { - reportErrorFunc("Source is nullptr"); + Lua::reportErrorFunc("Source is nullptr"); return 1; } const auto &destination = getBank(L, 2, true /* isGuild */); if (destination == nullptr) { - reportErrorFunc("Destination is nullptr"); + Lua::reportErrorFunc("Destination is nullptr"); return 1; } - const uint64_t amount = getNumber<uint64_t>(L, 3); - pushBoolean(L, source->transferTo(destination, amount)); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 3); + Lua::pushBoolean(L, source->transferTo(destination, amount)); return 1; } int BankFunctions::luaBankWithdraw(lua_State* L) { // Bank.withdraw(player, amount[, source = player]) - const auto &player = getPlayer(L, 1); + const auto &player = Lua::getPlayer(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - uint64_t amount = getNumber<uint64_t>(L, 2); + const uint64_t amount = Lua::getNumber<uint64_t>(L, 2); if (lua_gettop(L) == 2) { - const auto bank = std::make_shared<Bank>(player); - pushBoolean(L, bank->withdraw(player, amount)); + auto bank = std::make_shared<Bank>(player); + Lua::pushBoolean(L, bank->withdraw(player, amount)); return 1; } - auto source = getBank(L, 3); + const auto &source = getBank(L, 3); if (source == nullptr) { - reportErrorFunc("Source is nullptr"); + Lua::reportErrorFunc("Source is nullptr"); return 1; } - pushBoolean(L, source->withdraw(player, amount)); + Lua::pushBoolean(L, source->withdraw(player, amount)); return 1; } int BankFunctions::luaBankDeposit(lua_State* L) { // Bank.deposit(player, amount[, destination = player]) - const auto &player = getPlayer(L, 1); + const auto &player = Lua::getPlayer(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - const auto bank = std::make_shared<Bank>(player); + auto bank = std::make_shared<Bank>(player); uint64_t amount = 0; if (lua_isnumber(L, 2)) { - amount = getNumber<uint64_t>(L, 2); + amount = Lua::getNumber<uint64_t>(L, 2); } else if (lua_isnil(L, 2)) { amount = player->getMoney(); } if (lua_gettop(L) == 2) { - pushBoolean(L, g_game().removeMoney(player, amount) && bank->credit(amount)); + Lua::pushBoolean(L, g_game().removeMoney(player, amount) && bank->credit(amount)); return 1; } - auto destination = getBank(L, 3); + const auto &destination = getBank(L, 3); if (destination == nullptr) { - reportErrorFunc("Destination is nullptr"); + Lua::reportErrorFunc("Destination is nullptr"); return 1; } - pushBoolean(L, g_game().removeMoney(player, amount) && destination->credit(amount)); + Lua::pushBoolean(L, g_game().removeMoney(player, amount) && destination->credit(amount)); return 1; } std::shared_ptr<Bank> BankFunctions::getBank(lua_State* L, int32_t arg, bool isGuild /*= false*/) { - if (getUserdataType(L, arg) == LuaData_t::Guild) { - return std::make_shared<Bank>(getGuild(L, arg)); + if (Lua::getUserdataType(L, arg) == LuaData_t::Guild) { + return std::make_shared<Bank>(Lua::getGuild(L, arg)); } if (isGuild) { - const auto guild = getGuild(L, arg, true); + const auto &guild = Lua::getGuild(L, arg, true); if (!guild) { return nullptr; } return std::make_shared<Bank>(guild); } - std::shared_ptr<Player> player = getPlayer(L, arg, true); + const auto &player = Lua::getPlayer(L, arg, true); if (!player) { return nullptr; } diff --git a/src/lua/functions/core/game/bank_functions.hpp b/src/lua/functions/core/game/bank_functions.hpp index db450f49469..a93de48424b 100644 --- a/src/lua/functions/core/game/bank_functions.hpp +++ b/src/lua/functions/core/game/bank_functions.hpp @@ -9,23 +9,11 @@ #pragma once -#include "lua/scripts/luascript.hpp" - class Bank; -class BankFunctions final : LuaScriptInterface { +class BankFunctions { public: - static void init(lua_State* L) { - registerTable(L, "Bank"); - registerMethod(L, "Bank", "credit", BankFunctions::luaBankCredit); - registerMethod(L, "Bank", "debit", BankFunctions::luaBankDebit); - registerMethod(L, "Bank", "balance", BankFunctions::luaBankBalance); - registerMethod(L, "Bank", "hasBalance", BankFunctions::luaBankHasBalance); - registerMethod(L, "Bank", "transfer", BankFunctions::luaBankTransfer); - registerMethod(L, "Bank", "transferToGuild", BankFunctions::luaBankTransferToGuild); - registerMethod(L, "Bank", "withdraw", BankFunctions::luaBankWithdraw); - registerMethod(L, "Bank", "deposit", BankFunctions::luaBankDeposit); - } + static void init(lua_State* L); private: static int luaBankCredit(lua_State* L); diff --git a/src/lua/functions/core/game/config_functions.cpp b/src/lua/functions/core/game/config_functions.cpp index 7b4b34a9eb3..029895a43e5 100644 --- a/src/lua/functions/core/game/config_functions.cpp +++ b/src/lua/functions/core/game/config_functions.cpp @@ -10,20 +10,21 @@ #include "lua/functions/core/game/config_functions.hpp" #include "config/configmanager.hpp" +#include "lua/functions/lua_functions_loader.hpp" void ConfigFunctions::init(lua_State* L) { - registerTable(L, "configManager"); - registerMethod(L, "configManager", "getString", luaConfigManagerGetString); - registerMethod(L, "configManager", "getNumber", luaConfigManagerGetNumber); - registerMethod(L, "configManager", "getBoolean", luaConfigManagerGetBoolean); - registerMethod(L, "configManager", "getFloat", luaConfigManagerGetFloat); + Lua::registerTable(L, "configManager"); + Lua::registerMethod(L, "configManager", "getString", luaConfigManagerGetString); + Lua::registerMethod(L, "configManager", "getNumber", luaConfigManagerGetNumber); + Lua::registerMethod(L, "configManager", "getBoolean", luaConfigManagerGetBoolean); + Lua::registerMethod(L, "configManager", "getFloat", luaConfigManagerGetFloat); #define registerMagicEnumIn(L, tableName, enumValue) \ do { \ auto name = magic_enum::enum_name(enumValue).data(); \ - registerVariable(L, tableName, name, value); \ + Lua::registerVariable(L, tableName, name, value); \ } while (0) - registerTable(L, "configKeys"); + Lua::registerTable(L, "configKeys"); for (auto value : magic_enum::enum_values<ConfigKey_t>()) { auto enumName = magic_enum::enum_name(value).data(); if (enumName) { @@ -35,35 +36,35 @@ void ConfigFunctions::init(lua_State* L) { } int ConfigFunctions::luaConfigManagerGetString(lua_State* L) { - auto key = getNumber<ConfigKey_t>(L, -1); + const auto key = Lua::getNumber<ConfigKey_t>(L, -1); if (!key) { - reportErrorFunc("Wrong enum"); + Lua::reportErrorFunc("Wrong enum"); return 1; } - pushString(L, g_configManager().getString(getNumber<ConfigKey_t>(L, -1))); + Lua::pushString(L, g_configManager().getString(Lua::getNumber<ConfigKey_t>(L, -1))); return 1; } int ConfigFunctions::luaConfigManagerGetNumber(lua_State* L) { - auto key = getNumber<ConfigKey_t>(L, -1); + const auto key = Lua::getNumber<ConfigKey_t>(L, -1); if (!key) { - reportErrorFunc("Wrong enum"); + Lua::reportErrorFunc("Wrong enum"); return 1; } - lua_pushnumber(L, g_configManager().getNumber(getNumber<ConfigKey_t>(L, -1))); + lua_pushnumber(L, g_configManager().getNumber(Lua::getNumber<ConfigKey_t>(L, -1))); return 1; } int ConfigFunctions::luaConfigManagerGetBoolean(lua_State* L) { - auto key = getNumber<ConfigKey_t>(L, -1); + const auto key = Lua::getNumber<ConfigKey_t>(L, -1); if (!key) { - reportErrorFunc("Wrong enum"); + Lua::reportErrorFunc("Wrong enum"); return 1; } - pushBoolean(L, g_configManager().getBoolean(getNumber<ConfigKey_t>(L, -1))); + Lua::pushBoolean(L, g_configManager().getBoolean(Lua::getNumber<ConfigKey_t>(L, -1))); return 1; } @@ -71,18 +72,18 @@ int ConfigFunctions::luaConfigManagerGetFloat(lua_State* L) { // configManager.getFloat(key, shouldRound = true) // Ensure the first argument (key) is provided and is a valid enum - auto key = getNumber<ConfigKey_t>(L, 1); + const auto key = Lua::getNumber<ConfigKey_t>(L, 1); if (!key) { - reportErrorFunc("Wrong enum"); + Lua::reportErrorFunc("Wrong enum"); return 1; } // Check if the second argument (shouldRound) is provided and is a boolean; default to true if not provided - bool shouldRound = getBoolean(L, 2, true); + bool shouldRound = Lua::getBoolean(L, 2, true); float value = g_configManager().getFloat(key); double finalValue = shouldRound ? static_cast<double>(std::round(value * 100.0) / 100.0) : value; - g_logger().debug("[{}] key: {}, finalValue: {}, shouldRound: {}", __METHOD_NAME__, magic_enum::enum_name(key), finalValue, shouldRound); + g_logger().debug("[{}] key: {}, finalValue: {}, shouldRound: {}", __FUNCTION__, magic_enum::enum_name(key), finalValue, shouldRound); lua_pushnumber(L, finalValue); return 1; } diff --git a/src/lua/functions/core/game/config_functions.hpp b/src/lua/functions/core/game/config_functions.hpp index 9806a35f426..c22144ee08e 100644 --- a/src/lua/functions/core/game/config_functions.hpp +++ b/src/lua/functions/core/game/config_functions.hpp @@ -10,9 +10,7 @@ #pragma once #include "declarations.hpp" -#include "lua/scripts/luascript.hpp" - -class ConfigFunctions final : LuaScriptInterface { +class ConfigFunctions { public: static void init(lua_State* L); diff --git a/src/lua/functions/core/game/core_game_functions.hpp b/src/lua/functions/core/game/core_game_functions.hpp index 03bcc236daf..f5fe1c9da94 100644 --- a/src/lua/functions/core/game/core_game_functions.hpp +++ b/src/lua/functions/core/game/core_game_functions.hpp @@ -19,6 +19,12 @@ class CoreGameFunctions final : LuaScriptInterface { public: + explicit CoreGameFunctions(lua_State* L) : + LuaScriptInterface("CoreGameFunctions") { + init(L); + } + ~CoreGameFunctions() override = default; + static void init(lua_State* L) { ConfigFunctions::init(L); GameFunctions::init(L); diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index 064bdd166e1..aad4b71d06c 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -7,39 +7,118 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/core/game/game_functions.hpp" + #include "core.hpp" #include "creatures/monsters/monster.hpp" +#include "creatures/monsters/monsters.hpp" +#include "creatures/npcs/npc.hpp" +#include "creatures/players/achievement/player_achievement.hpp" +#include "creatures/players/player.hpp" #include "game/functions/game_reload.hpp" #include "game/game.hpp" -#include "items/item.hpp" -#include "io/iobestiary.hpp" -#include "io/io_bosstiary.hpp" -#include "io/iologindata.hpp" -#include "lua/functions/core/game/game_functions.hpp" -#include "lua/functions/events/event_callback_functions.hpp" #include "game/scheduling/dispatcher.hpp" +#include "io/io_bosstiary.hpp" +#include "io/iobestiary.hpp" +#include "items/item.hpp" +#include "lua/callbacks/event_callback.hpp" +#include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/events.hpp" #include "lua/creature/talkaction.hpp" #include "lua/functions/creatures/npc/npc_type_functions.hpp" +#include "lua/functions/events/event_callback_functions.hpp" #include "lua/scripts/lua_environment.hpp" -#include "lua/creature/events.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" -#include "creatures/players/achievement/player_achievement.hpp" -#include "creatures/players/cyclopedia/player_badge.hpp" -#include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "creatures/players/cyclopedia/player_title.hpp" #include "map/spectators.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void GameFunctions::init(lua_State* L) { + Lua::registerTable(L, "Game"); + + Lua::registerMethod(L, "Game", "createNpcType", GameFunctions::luaGameCreateNpcType); + Lua::registerMethod(L, "Game", "createMonsterType", GameFunctions::luaGameCreateMonsterType); + + Lua::registerMethod(L, "Game", "getSpectators", GameFunctions::luaGameGetSpectators); + + Lua::registerMethod(L, "Game", "getBoostedCreature", GameFunctions::luaGameGetBoostedCreature); + Lua::registerMethod(L, "Game", "getBestiaryList", GameFunctions::luaGameGetBestiaryList); + + Lua::registerMethod(L, "Game", "getPlayers", GameFunctions::luaGameGetPlayers); + Lua::registerMethod(L, "Game", "loadMap", GameFunctions::luaGameLoadMap); + Lua::registerMethod(L, "Game", "loadMapChunk", GameFunctions::luaGameloadMapChunk); + + Lua::registerMethod(L, "Game", "getExperienceForLevel", GameFunctions::luaGameGetExperienceForLevel); + Lua::registerMethod(L, "Game", "getMonsterCount", GameFunctions::luaGameGetMonsterCount); + Lua::registerMethod(L, "Game", "getPlayerCount", GameFunctions::luaGameGetPlayerCount); + Lua::registerMethod(L, "Game", "getNpcCount", GameFunctions::luaGameGetNpcCount); + Lua::registerMethod(L, "Game", "getMonsterTypes", GameFunctions::luaGameGetMonsterTypes); + + Lua::registerMethod(L, "Game", "getTowns", GameFunctions::luaGameGetTowns); + Lua::registerMethod(L, "Game", "getHouses", GameFunctions::luaGameGetHouses); + + Lua::registerMethod(L, "Game", "getGameState", GameFunctions::luaGameGetGameState); + Lua::registerMethod(L, "Game", "setGameState", GameFunctions::luaGameSetGameState); + + Lua::registerMethod(L, "Game", "getWorldType", GameFunctions::luaGameGetWorldType); + Lua::registerMethod(L, "Game", "setWorldType", GameFunctions::luaGameSetWorldType); + + Lua::registerMethod(L, "Game", "getReturnMessage", GameFunctions::luaGameGetReturnMessage); + + Lua::registerMethod(L, "Game", "createItem", GameFunctions::luaGameCreateItem); + Lua::registerMethod(L, "Game", "createContainer", GameFunctions::luaGameCreateContainer); + Lua::registerMethod(L, "Game", "createMonster", GameFunctions::luaGameCreateMonster); + Lua::registerMethod(L, "Game", "createNpc", GameFunctions::luaGameCreateNpc); + Lua::registerMethod(L, "Game", "generateNpc", GameFunctions::luaGameGenerateNpc); + Lua::registerMethod(L, "Game", "createTile", GameFunctions::luaGameCreateTile); + Lua::registerMethod(L, "Game", "createBestiaryCharm", GameFunctions::luaGameCreateBestiaryCharm); + + Lua::registerMethod(L, "Game", "createItemClassification", GameFunctions::luaGameCreateItemClassification); + + Lua::registerMethod(L, "Game", "getBestiaryCharm", GameFunctions::luaGameGetBestiaryCharm); + + Lua::registerMethod(L, "Game", "startRaid", GameFunctions::luaGameStartRaid); + + Lua::registerMethod(L, "Game", "getClientVersion", GameFunctions::luaGameGetClientVersion); + + Lua::registerMethod(L, "Game", "reload", GameFunctions::luaGameReload); + + Lua::registerMethod(L, "Game", "hasDistanceEffect", GameFunctions::luaGameHasDistanceEffect); + Lua::registerMethod(L, "Game", "hasEffect", GameFunctions::luaGameHasEffect); + Lua::registerMethod(L, "Game", "getOfflinePlayer", GameFunctions::luaGameGetOfflinePlayer); + Lua::registerMethod(L, "Game", "getNormalizedPlayerName", GameFunctions::luaGameGetNormalizedPlayerName); + Lua::registerMethod(L, "Game", "getNormalizedGuildName", GameFunctions::luaGameGetNormalizedGuildName); + + Lua::registerMethod(L, "Game", "addInfluencedMonster", GameFunctions::luaGameAddInfluencedMonster); + Lua::registerMethod(L, "Game", "removeInfluencedMonster", GameFunctions::luaGameRemoveInfluencedMonster); + Lua::registerMethod(L, "Game", "getInfluencedMonsters", GameFunctions::luaGameGetInfluencedMonsters); + Lua::registerMethod(L, "Game", "makeFiendishMonster", GameFunctions::luaGameMakeFiendishMonster); + Lua::registerMethod(L, "Game", "removeFiendishMonster", GameFunctions::luaGameRemoveFiendishMonster); + Lua::registerMethod(L, "Game", "getFiendishMonsters", GameFunctions::luaGameGetFiendishMonsters); + Lua::registerMethod(L, "Game", "getBoostedBoss", GameFunctions::luaGameGetBoostedBoss); + + Lua::registerMethod(L, "Game", "getLadderIds", GameFunctions::luaGameGetLadderIds); + Lua::registerMethod(L, "Game", "getDummies", GameFunctions::luaGameGetDummies); + + Lua::registerMethod(L, "Game", "getTalkActions", GameFunctions::luaGameGetTalkActions); + Lua::registerMethod(L, "Game", "getEventCallbacks", GameFunctions::luaGameGetEventCallbacks); + + Lua::registerMethod(L, "Game", "registerAchievement", GameFunctions::luaGameRegisterAchievement); + Lua::registerMethod(L, "Game", "getAchievementInfoById", GameFunctions::luaGameGetAchievementInfoById); + Lua::registerMethod(L, "Game", "getAchievementInfoByName", GameFunctions::luaGameGetAchievementInfoByName); + Lua::registerMethod(L, "Game", "getSecretAchievements", GameFunctions::luaGameGetSecretAchievements); + Lua::registerMethod(L, "Game", "getPublicAchievements", GameFunctions::luaGameGetPublicAchievements); + Lua::registerMethod(L, "Game", "getAchievements", GameFunctions::luaGameGetAchievements); +} // Game int GameFunctions::luaGameCreateMonsterType(lua_State* L) { // Game.createMonsterType(name[, variant = ""[, alternateName = ""]]) - if (isString(L, 1)) { - const auto name = getString(L, 1); + if (Lua::isString(L, 1)) { + const auto name = Lua::getString(L, 1); std::string uniqueName = name; - auto variant = getString(L, 2, ""); - const auto alternateName = getString(L, 3, ""); + auto variant = Lua::getString(L, 2, ""); + const auto alternateName = Lua::getString(L, 3, ""); std::set<std::string> names; - auto monsterType = std::make_shared<MonsterType>(name); + const auto monsterType = std::make_shared<MonsterType>(name); if (!monsterType) { lua_pushstring(L, "MonsterType is nullptr"); lua_error(L); @@ -73,8 +152,8 @@ int GameFunctions::luaGameCreateMonsterType(lua_State* L) { } } - pushUserdata<MonsterType>(L, monsterType); - setMetatable(L, -1, "MonsterType"); + Lua::pushUserdata<MonsterType>(L, monsterType); + Lua::setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } @@ -87,13 +166,13 @@ int GameFunctions::luaGameCreateNpcType(lua_State* L) { int GameFunctions::luaGameGetSpectators(lua_State* L) { // Game.getSpectators(position[, multifloor = false[, onlyPlayer = false[, minRangeX = 0[, maxRangeX = 0[, minRangeY = 0[, maxRangeY = 0]]]]]]) - const Position &position = getPosition(L, 1); - bool multifloor = getBoolean(L, 2, false); - bool onlyPlayers = getBoolean(L, 3, false); - int32_t minRangeX = getNumber<int32_t>(L, 4, 0); - int32_t maxRangeX = getNumber<int32_t>(L, 5, 0); - int32_t minRangeY = getNumber<int32_t>(L, 6, 0); - int32_t maxRangeY = getNumber<int32_t>(L, 7, 0); + const Position &position = Lua::getPosition(L, 1); + const bool multifloor = Lua::getBoolean(L, 2, false); + const bool onlyPlayers = Lua::getBoolean(L, 3, false); + const auto minRangeX = Lua::getNumber<int32_t>(L, 4, 0); + const auto maxRangeX = Lua::getNumber<int32_t>(L, 5, 0); + const auto minRangeY = Lua::getNumber<int32_t>(L, 6, 0); + const auto maxRangeY = Lua::getNumber<int32_t>(L, 7, 0); Spectators spectators; @@ -106,9 +185,9 @@ int GameFunctions::luaGameGetSpectators(lua_State* L) { lua_createtable(L, spectators.size(), 0); int index = 0; - for (std::shared_ptr<Creature> creature : spectators) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + for (const auto &creature : spectators) { + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; @@ -116,7 +195,7 @@ int GameFunctions::luaGameGetSpectators(lua_State* L) { int GameFunctions::luaGameGetBoostedCreature(lua_State* L) { // Game.getBoostedCreature() - pushString(L, g_game().getBoostedMonsterName()); + Lua::pushString(L, g_game().getBoostedMonsterName()); return 1; } @@ -124,34 +203,34 @@ int GameFunctions::luaGameGetBestiaryList(lua_State* L) { // Game.getBestiaryList([bool[string or BestiaryType_t]]) lua_newtable(L); int index = 0; - bool name = getBoolean(L, 2, false); + const bool name = Lua::getBoolean(L, 2, false); if (lua_gettop(L) <= 2) { - std::map<uint16_t, std::string> mtype_list = g_game().getBestiaryList(); - for (auto ita : mtype_list) { + const std::map<uint16_t, std::string> &mtype_list = g_game().getBestiaryList(); + for (const auto &ita : mtype_list) { if (name) { - pushString(L, ita.second); + Lua::pushString(L, ita.second); } else { lua_pushnumber(L, ita.first); } lua_rawseti(L, -2, ++index); } } else { - if (isNumber(L, 2)) { - std::map<uint16_t, std::string> tmplist = g_iobestiary().findRaceByName("CANARY", false, getNumber<BestiaryType_t>(L, 2)); - for (auto itb : tmplist) { + if (Lua::isNumber(L, 2)) { + const std::map<uint16_t, std::string> tmplist = g_iobestiary().findRaceByName("CANARY", false, Lua::getNumber<BestiaryType_t>(L, 2)); + for (const auto &itb : tmplist) { if (name) { - pushString(L, itb.second); + Lua::pushString(L, itb.second); } else { lua_pushnumber(L, itb.first); } lua_rawseti(L, -2, ++index); } } else { - std::map<uint16_t, std::string> tmplist = g_iobestiary().findRaceByName(getString(L, 2)); - for (auto itc : tmplist) { + const std::map<uint16_t, std::string> tmplist = g_iobestiary().findRaceByName(Lua::getString(L, 2)); + for (const auto &itc : tmplist) { if (name) { - pushString(L, itc.second); + Lua::pushString(L, itc.second); } else { lua_pushnumber(L, itc.first); } @@ -168,8 +247,8 @@ int GameFunctions::luaGameGetPlayers(lua_State* L) { int index = 0; for (const auto &playerEntry : g_game().getPlayers()) { - pushUserdata<Player>(L, playerEntry.second); - setMetatable(L, -1, "Player"); + Lua::pushUserdata<Player>(L, playerEntry.second); + Lua::setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; @@ -177,24 +256,24 @@ int GameFunctions::luaGameGetPlayers(lua_State* L) { int GameFunctions::luaGameLoadMap(lua_State* L) { // Game.loadMap(path) - const std::string &path = getString(L, 1); + const std::string &path = Lua::getString(L, 1); g_dispatcher().addEvent([path]() { g_game().loadMap(path); }, __FUNCTION__); return 0; } int GameFunctions::luaGameloadMapChunk(lua_State* L) { // Game.loadMapChunk(path, position, remove) - const std::string &path = getString(L, 1); - const Position &position = getPosition(L, 2); + const std::string &path = Lua::getString(L, 1); + const Position &position = Lua::getPosition(L, 2); g_dispatcher().addEvent([path, position]() { g_game().loadMap(path, position); }, __FUNCTION__); return 0; } int GameFunctions::luaGameGetExperienceForLevel(lua_State* L) { // Game.getExperienceForLevel(level) - const uint32_t level = getNumber<uint32_t>(L, 1); + const uint32_t level = Lua::getNumber<uint32_t>(L, 1); if (level == 0) { - reportErrorFunc("Level must be greater than 0."); + Lua::reportErrorFunc("Level must be greater than 0."); } else { lua_pushnumber(L, Player::getExpForLevel(level)); } @@ -225,8 +304,8 @@ int GameFunctions::luaGameGetMonsterTypes(lua_State* L) { lua_createtable(L, type.size(), 0); for (const auto &[typeName, mType] : type) { - pushUserdata<MonsterType>(L, mType); - setMetatable(L, -1, "MonsterType"); + Lua::pushUserdata<MonsterType>(L, mType); + Lua::setMetatable(L, -1, "MonsterType"); lua_setfield(L, -2, typeName.c_str()); } return 1; @@ -238,9 +317,9 @@ int GameFunctions::luaGameGetTowns(lua_State* L) { lua_createtable(L, towns.size(), 0); int index = 0; - for (auto townEntry : towns) { - pushUserdata<Town>(L, townEntry.second); - setMetatable(L, -1, "Town"); + for (const auto &townEntry : towns) { + Lua::pushUserdata<Town>(L, townEntry.second); + Lua::setMetatable(L, -1, "Town"); lua_rawseti(L, -2, ++index); } return 1; @@ -252,9 +331,9 @@ int GameFunctions::luaGameGetHouses(lua_State* L) { lua_createtable(L, houses.size(), 0); int index = 0; - for (auto houseEntry : houses) { - pushUserdata<House>(L, houseEntry.second); - setMetatable(L, -1, "House"); + for (const auto &houseEntry : houses) { + Lua::pushUserdata<House>(L, houseEntry.second); + Lua::setMetatable(L, -1, "House"); lua_rawseti(L, -2, ++index); } return 1; @@ -268,9 +347,9 @@ int GameFunctions::luaGameGetGameState(lua_State* L) { int GameFunctions::luaGameSetGameState(lua_State* L) { // Game.setGameState(state) - GameState_t state = getNumber<GameState_t>(L, 1); + const GameState_t state = Lua::getNumber<GameState_t>(L, 1); g_game().setGameState(state); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -282,40 +361,40 @@ int GameFunctions::luaGameGetWorldType(lua_State* L) { int GameFunctions::luaGameSetWorldType(lua_State* L) { // Game.setWorldType(type) - WorldType_t type = getNumber<WorldType_t>(L, 1); + const WorldType_t type = Lua::getNumber<WorldType_t>(L, 1); g_game().setWorldType(type); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GameFunctions::luaGameGetReturnMessage(lua_State* L) { // Game.getReturnMessage(value) - ReturnValue value = getNumber<ReturnValue>(L, 1); - pushString(L, getReturnMessage(value)); + const ReturnValue value = Lua::getNumber<ReturnValue>(L, 1); + Lua::pushString(L, getReturnMessage(value)); return 1; } int GameFunctions::luaGameCreateItem(lua_State* L) { // Game.createItem(itemId or name[, count[, position]]) uint16_t itemId; - if (isNumber(L, 1)) { - itemId = getNumber<uint16_t>(L, 1); + if (Lua::isNumber(L, 1)) { + itemId = Lua::getNumber<uint16_t>(L, 1); } else { - itemId = Item::items.getItemIdByName(getString(L, 1)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 1)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t count = getNumber<int32_t>(L, 2, 1); + const auto count = Lua::getNumber<int32_t>(L, 2, 1); int32_t itemCount = 1; int32_t subType = 1; const ItemType &it = Item::items[itemId]; if (it.hasSubType()) { if (it.stackable) { - itemCount = std::ceil(count / (float_t)it.stackSize); + itemCount = std::ceil(count / static_cast<float_t>(it.stackSize)); } subType = count; @@ -325,10 +404,10 @@ int GameFunctions::luaGameCreateItem(lua_State* L) { Position position; if (lua_gettop(L) >= 3) { - position = getPosition(L, 3); + position = Lua::getPosition(L, 3); } - bool hasTable = itemCount > 1; + const bool hasTable = itemCount > 1; if (hasTable) { lua_newtable(L); } else if (itemCount == 0) { @@ -343,7 +422,7 @@ int GameFunctions::luaGameCreateItem(lua_State* L) { subType -= stackCount; } - std::shared_ptr<Item> item = Item::CreateItem(itemId, stackCount); + const auto &item = Item::CreateItem(itemId, stackCount); if (!item) { if (!hasTable) { lua_pushnil(L); @@ -352,7 +431,7 @@ int GameFunctions::luaGameCreateItem(lua_State* L) { } if (position.x != 0) { - std::shared_ptr<Tile> tile = g_game().map.getTile(position); + const auto &tile = g_game().map.getTile(position); if (!tile) { if (!hasTable) { lua_pushnil(L); @@ -368,18 +447,18 @@ int GameFunctions::luaGameCreateItem(lua_State* L) { return 1; } } else { - getScriptEnv()->addTempItem(item); + Lua::getScriptEnv()->addTempItem(item); item->setParent(VirtualCylinder::virtualCylinder); } if (hasTable) { lua_pushnumber(L, i); - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); lua_settable(L, -3); } else { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } } @@ -388,27 +467,27 @@ int GameFunctions::luaGameCreateItem(lua_State* L) { int GameFunctions::luaGameCreateContainer(lua_State* L) { // Game.createContainer(itemId, size[, position]) - uint16_t size = getNumber<uint16_t>(L, 2); + const uint16_t size = Lua::getNumber<uint16_t>(L, 2); uint16_t id; - if (isNumber(L, 1)) { - id = getNumber<uint16_t>(L, 1); + if (Lua::isNumber(L, 1)) { + id = Lua::getNumber<uint16_t>(L, 1); } else { - id = Item::items.getItemIdByName(getString(L, 1)); + id = Item::items.getItemIdByName(Lua::getString(L, 1)); if (id == 0) { lua_pushnil(L); return 1; } } - std::shared_ptr<Container> container = Item::CreateItemAsContainer(id, size); + const auto &container = Item::CreateItemAsContainer(id, size); if (!container) { lua_pushnil(L); return 1; } if (lua_gettop(L) >= 3) { - const Position &position = getPosition(L, 3); - std::shared_ptr<Tile> tile = g_game().map.getTile(position); + const Position &position = Lua::getPosition(L, 3); + const auto &tile = g_game().map.getTile(position); if (!tile) { lua_pushnil(L); return 1; @@ -416,18 +495,18 @@ int GameFunctions::luaGameCreateContainer(lua_State* L) { g_game().internalAddItem(tile, container, INDEX_WHEREEVER, FLAG_NOLIMIT); } else { - getScriptEnv()->addTempItem(container); + Lua::getScriptEnv()->addTempItem(container); container->setParent(VirtualCylinder::virtualCylinder); } - pushUserdata<Container>(L, container); - setMetatable(L, -1, "Container"); + Lua::pushUserdata<Container>(L, container); + Lua::setMetatable(L, -1, "Container"); return 1; } int GameFunctions::luaGameCreateMonster(lua_State* L) { // Game.createMonster(monsterName, position[, extended = false[, force = false[, master = nil]]]) - const auto &monster = Monster::createMonster(getString(L, 1)); + const auto &monster = Monster::createMonster(Lua::getString(L, 1)); if (!monster) { lua_pushnil(L); return 1; @@ -435,18 +514,16 @@ int GameFunctions::luaGameCreateMonster(lua_State* L) { bool isSummon = false; if (lua_gettop(L) >= 5) { - if (const auto &master = getCreature(L, 5)) { + if (const auto &master = Lua::getCreature(L, 5)) { monster->setMaster(master, true); isSummon = true; } } - const Position &position = getPosition(L, 2); - bool extended = getBoolean(L, 3, false); - bool force = getBoolean(L, 4, false); + const Position &position = Lua::getPosition(L, 2); + const bool extended = Lua::getBoolean(L, 3, false); + const bool force = Lua::getBoolean(L, 4, false); if (g_game().placeCreature(monster, position, extended, force)) { - g_events().eventMonsterOnSpawn(monster, position); - g_callbacks().executeCallback(EventCallback_t::monsterOnSpawn, &EventCallback::monsterOnSpawn, monster, position); monster->onSpawn(); const auto &mtype = monster->getMonsterType(); if (mtype && mtype->info.raceid > 0 && mtype->info.bosstiaryRace == BosstiaryRarity_t::RARITY_ARCHFOE) { @@ -457,8 +534,8 @@ int GameFunctions::luaGameCreateMonster(lua_State* L) { } } - pushUserdata<Monster>(L, monster); - setMetatable(L, -1, "Monster"); + Lua::pushUserdata<Monster>(L, monster); + Lua::setMetatable(L, -1, "Monster"); } else { if (isSummon) { monster->setMaster(nullptr); @@ -471,31 +548,31 @@ int GameFunctions::luaGameCreateMonster(lua_State* L) { int GameFunctions::luaGameGenerateNpc(lua_State* L) { // Game.generateNpc(npcName) - std::shared_ptr<Npc> npc = Npc::createNpc(getString(L, 1)); + const auto &npc = Npc::createNpc(Lua::getString(L, 1)); if (!npc) { lua_pushnil(L); return 1; } else { - pushUserdata<Npc>(L, npc); - setMetatable(L, -1, "Npc"); + Lua::pushUserdata<Npc>(L, npc); + Lua::setMetatable(L, -1, "Npc"); } return 1; } int GameFunctions::luaGameCreateNpc(lua_State* L) { // Game.createNpc(npcName, position[, extended = false[, force = false]]) - std::shared_ptr<Npc> npc = Npc::createNpc(getString(L, 1)); + const auto &npc = Npc::createNpc(Lua::getString(L, 1)); if (!npc) { lua_pushnil(L); return 1; } - const Position &position = getPosition(L, 2); - bool extended = getBoolean(L, 3, false); - bool force = getBoolean(L, 4, false); + const Position &position = Lua::getPosition(L, 2); + const bool extended = Lua::getBoolean(L, 3, false); + const bool force = Lua::getBoolean(L, 4, false); if (g_game().placeCreature(npc, position, extended, force)) { - pushUserdata<Npc>(L, npc); - setMetatable(L, -1, "Npc"); + Lua::pushUserdata<Npc>(L, npc); + Lua::setMetatable(L, -1, "Npc"); } else { lua_pushnil(L); } @@ -507,18 +584,18 @@ int GameFunctions::luaGameCreateTile(lua_State* L) { // Game.createTile(position[, isDynamic = false]) Position position; bool isDynamic; - if (isTable(L, 1)) { - position = getPosition(L, 1); - isDynamic = getBoolean(L, 2, false); + if (Lua::isTable(L, 1)) { + position = Lua::getPosition(L, 1); + isDynamic = Lua::getBoolean(L, 2, false); } else { - position.x = getNumber<uint16_t>(L, 1); - position.y = getNumber<uint16_t>(L, 2); - position.z = getNumber<uint16_t>(L, 3); - isDynamic = getBoolean(L, 4, false); + position.x = Lua::getNumber<uint16_t>(L, 1); + position.y = Lua::getNumber<uint16_t>(L, 2); + position.z = Lua::getNumber<uint16_t>(L, 3); + isDynamic = Lua::getBoolean(L, 4, false); } - pushUserdata(L, g_game().map.getOrCreateTile(position, isDynamic)); - setMetatable(L, -1, "Tile"); + Lua::pushUserdata(L, g_game().map.getOrCreateTile(position, isDynamic)); + Lua::setMetatable(L, -1, "Tile"); return 1; } @@ -529,8 +606,8 @@ int GameFunctions::luaGameGetBestiaryCharm(lua_State* L) { int index = 0; for (const auto &charmPtr : c_list) { - pushUserdata<Charm>(L, charmPtr); - setMetatable(L, -1, "Charm"); + Lua::pushUserdata<Charm>(L, charmPtr); + Lua::setMetatable(L, -1, "Charm"); lua_rawseti(L, -2, ++index); } return 1; @@ -538,9 +615,9 @@ int GameFunctions::luaGameGetBestiaryCharm(lua_State* L) { int GameFunctions::luaGameCreateBestiaryCharm(lua_State* L) { // Game.createBestiaryCharm(id) - if (const std::shared_ptr<Charm> charm = g_iobestiary().getBestiaryCharm(static_cast<charmRune_t>(getNumber<int8_t>(L, 1, 0)), true)) { - pushUserdata<Charm>(L, charm); - setMetatable(L, -1, "Charm"); + if (const std::shared_ptr<Charm> &charm = g_iobestiary().getBestiaryCharm(static_cast<charmRune_t>(Lua::getNumber<int8_t>(L, 1, 0)), true)) { + Lua::pushUserdata<Charm>(L, charm); + Lua::setMetatable(L, -1, "Charm"); } else { lua_pushnil(L); } @@ -549,10 +626,10 @@ int GameFunctions::luaGameCreateBestiaryCharm(lua_State* L) { int GameFunctions::luaGameCreateItemClassification(lua_State* L) { // Game.createItemClassification(id) - const ItemClassification* itemClassification = g_game().getItemsClassification(getNumber<uint8_t>(L, 1), true); + const ItemClassification* itemClassification = g_game().getItemsClassification(Lua::getNumber<uint8_t>(L, 1), true); if (itemClassification) { - pushUserdata<const ItemClassification>(L, itemClassification); - setMetatable(L, -1, "ItemClassification"); + Lua::pushUserdata<const ItemClassification>(L, itemClassification); + Lua::setMetatable(L, -1, "ItemClassification"); } else { lua_pushnil(L); } @@ -561,9 +638,9 @@ int GameFunctions::luaGameCreateItemClassification(lua_State* L) { int GameFunctions::luaGameStartRaid(lua_State* L) { // Game.startRaid(raidName) - const std::string &raidName = getString(L, 1); + const std::string &raidName = Lua::getString(L, 1); - const auto raid = g_game().raids.getRaidByName(raidName); + const auto &raid = g_game().raids.getRaidByName(raidName); if (!raid || !raid->isLoaded()) { lua_pushnumber(L, RETURNVALUE_NOSUCHRAIDEXISTS); return 1; @@ -583,66 +660,66 @@ int GameFunctions::luaGameStartRaid(lua_State* L) { int GameFunctions::luaGameGetClientVersion(lua_State* L) { // Game.getClientVersion() lua_createtable(L, 0, 3); - setField(L, "min", CLIENT_VERSION); - setField(L, "max", CLIENT_VERSION); - std::string version = fmt::format("{}.{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER); - setField(L, "string", version); + Lua::setField(L, "min", CLIENT_VERSION); + Lua::setField(L, "max", CLIENT_VERSION); + const std::string version = fmt::format("{}.{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER); + Lua::setField(L, "string", version); return 1; } int GameFunctions::luaGameReload(lua_State* L) { // Game.reload(reloadType) - Reload_t reloadType = getNumber<Reload_t>(L, 1); - if (g_gameReload().getReloadNumber(reloadType) == g_gameReload().getReloadNumber(Reload_t::RELOAD_TYPE_NONE)) { - reportErrorFunc("Reload type is none"); - pushBoolean(L, false); + const Reload_t reloadType = Lua::getNumber<Reload_t>(L, 1); + if (GameReload::getReloadNumber(reloadType) == GameReload::getReloadNumber(Reload_t::RELOAD_TYPE_NONE)) { + Lua::reportErrorFunc("Reload type is none"); + Lua::pushBoolean(L, false); return 0; } - if (g_gameReload().getReloadNumber(reloadType) >= g_gameReload().getReloadNumber(Reload_t::RELOAD_TYPE_LAST)) { - reportErrorFunc("Reload type not exist"); - pushBoolean(L, false); + if (GameReload::getReloadNumber(reloadType) >= GameReload::getReloadNumber(Reload_t::RELOAD_TYPE_LAST)) { + Lua::reportErrorFunc("Reload type not exist"); + Lua::pushBoolean(L, false); return 0; } - pushBoolean(L, g_gameReload().init(reloadType)); + Lua::pushBoolean(L, GameReload::init(reloadType)); lua_gc(g_luaEnvironment().getLuaState(), LUA_GCCOLLECT, 0); return 1; } int GameFunctions::luaGameHasEffect(lua_State* L) { // Game.hasEffect(effectId) - uint16_t effectId = getNumber<uint16_t>(L, 1); - pushBoolean(L, g_game().hasEffect(effectId)); + const uint16_t effectId = Lua::getNumber<uint16_t>(L, 1); + Lua::pushBoolean(L, g_game().hasEffect(effectId)); return 1; } int GameFunctions::luaGameHasDistanceEffect(lua_State* L) { // Game.hasDistanceEffect(effectId) - uint16_t effectId = getNumber<uint16_t>(L, 1); - pushBoolean(L, g_game().hasDistanceEffect(effectId)); + const uint16_t effectId = Lua::getNumber<uint16_t>(L, 1); + Lua::pushBoolean(L, g_game().hasDistanceEffect(effectId)); return 1; } int GameFunctions::luaGameGetOfflinePlayer(lua_State* L) { // Game.getOfflinePlayer(name or id) std::shared_ptr<Player> player = nullptr; - if (isNumber(L, 1)) { - uint32_t id = getNumber<uint32_t>(L, 1); + if (Lua::isNumber(L, 1)) { + const uint32_t id = Lua::getNumber<uint32_t>(L, 1); if (id >= Player::getFirstID() && id <= Player::getLastID()) { player = g_game().getPlayerByID(id, true); } else { player = g_game().getPlayerByGUID(id, true); } - } else if (isString(L, 1)) { - auto name = getString(L, 1); + } else if (Lua::isString(L, 1)) { + const auto name = Lua::getString(L, 1); player = g_game().getPlayerByName(name, true); } if (!player) { lua_pushnil(L); } else { - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); } return 1; @@ -650,11 +727,11 @@ int GameFunctions::luaGameGetOfflinePlayer(lua_State* L) { int GameFunctions::luaGameGetNormalizedPlayerName(lua_State* L) { // Game.getNormalizedPlayerName(name[, isNewName = false]) - auto name = getString(L, 1); - auto isNewName = getBoolean(L, 2, false); - std::shared_ptr<Player> player = g_game().getPlayerByName(name, true, isNewName); + const auto name = Lua::getString(L, 1); + const auto isNewName = Lua::getBoolean(L, 2, false); + const auto &player = g_game().getPlayerByName(name, true, isNewName); if (player) { - pushString(L, player->getName()); + Lua::pushString(L, player->getName()); } else { lua_pushnil(L); } @@ -663,10 +740,10 @@ int GameFunctions::luaGameGetNormalizedPlayerName(lua_State* L) { int GameFunctions::luaGameGetNormalizedGuildName(lua_State* L) { // Game.getNormalizedGuildName(name) - auto name = getString(L, 1); - const auto guild = g_game().getGuildByName(name, true); + const auto name = Lua::getString(L, 1); + const auto &guild = g_game().getGuildByName(name, true); if (guild) { - pushString(L, guild->getName()); + Lua::pushString(L, guild->getName()); } else { lua_pushnil(L); } @@ -675,10 +752,10 @@ int GameFunctions::luaGameGetNormalizedGuildName(lua_State* L) { int GameFunctions::luaGameAddInfluencedMonster(lua_State* L) { // Game.addInfluencedMonster(monster) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -688,15 +765,15 @@ int GameFunctions::luaGameAddInfluencedMonster(lua_State* L) { int GameFunctions::luaGameRemoveInfluencedMonster(lua_State* L) { // Game.removeInfluencedMonster(monsterId) - uint32_t monsterId = getNumber<uint32_t>(L, 1); - auto create = getBoolean(L, 2, false); + const uint32_t monsterId = Lua::getNumber<uint32_t>(L, 1); + const auto create = Lua::getBoolean(L, 2, false); lua_pushnumber(L, g_game().removeInfluencedMonster(monsterId, create)); return 1; } int GameFunctions::luaGameGetInfluencedMonsters(lua_State* L) { // Game.getInfluencedMonsters() - const auto monsters = g_game().getInfluencedMonsters(); + const auto &monsters = g_game().getInfluencedMonsters(); lua_createtable(L, static_cast<int>(monsters.size()), 0); int index = 0; for (const auto monsterId : monsters) { @@ -713,7 +790,7 @@ int GameFunctions::luaGameGetLadderIds(lua_State* L) { const auto &ladders = Item::items.getLadders(); lua_createtable(L, static_cast<int>(ladders.size()), 0); int index = 0; - for (const auto ladderId : ladders) { + for (const auto &ladderId : ladders) { ++index; lua_pushnumber(L, static_cast<lua_Number>(ladderId)); lua_rawseti(L, -2, index); @@ -743,23 +820,23 @@ int GameFunctions::luaGameGetDummies(lua_State* L) { int GameFunctions::luaGameMakeFiendishMonster(lua_State* L) { // Game.makeFiendishMonster(monsterId[default= 0]) - uint32_t monsterId = getNumber<uint32_t>(L, 1, 0); - auto createForgeableMonsters = getBoolean(L, 2, false); + const auto monsterId = Lua::getNumber<uint32_t>(L, 1, 0); + const auto createForgeableMonsters = Lua::getBoolean(L, 2, false); lua_pushnumber(L, g_game().makeFiendishMonster(monsterId, createForgeableMonsters)); return 1; } int GameFunctions::luaGameRemoveFiendishMonster(lua_State* L) { // Game.removeFiendishMonster(monsterId) - uint32_t monsterId = getNumber<uint32_t>(L, 1); - auto create = getBoolean(L, 2, false); + const uint32_t monsterId = Lua::getNumber<uint32_t>(L, 1); + const auto create = Lua::getBoolean(L, 2, false); lua_pushnumber(L, g_game().removeFiendishMonster(monsterId, create)); return 1; } int GameFunctions::luaGameGetFiendishMonsters(lua_State* L) { // Game.getFiendishMonsters() - const auto monsters = g_game().getFiendishMonsters(); + const auto &monsters = g_game().getFiendishMonsters(); lua_createtable(L, static_cast<int>(monsters.size()), 0); int index = 0; @@ -774,7 +851,7 @@ int GameFunctions::luaGameGetFiendishMonsters(lua_State* L) { int GameFunctions::luaGameGetBoostedBoss(lua_State* L) { // Game.getBoostedBoss() - pushString(L, g_ioBosstiary().getBoostedBossName()); + Lua::pushString(L, g_ioBosstiary().getBoostedBossName()); return 1; } @@ -784,8 +861,8 @@ int GameFunctions::luaGameGetTalkActions(lua_State* L) { lua_createtable(L, static_cast<int>(talkactionsMap.size()), 0); for (const auto &[talkName, talkactionSharedPtr] : talkactionsMap) { - pushUserdata<TalkAction>(L, talkactionSharedPtr); - setMetatable(L, -1, "TalkAction"); + Lua::pushUserdata<TalkAction>(L, talkactionSharedPtr); + Lua::setMetatable(L, -1, "TalkAction"); lua_setfield(L, -2, talkName.c_str()); } return 1; @@ -794,7 +871,7 @@ int GameFunctions::luaGameGetTalkActions(lua_State* L) { int GameFunctions::luaGameGetEventCallbacks(lua_State* L) { lua_createtable(L, 0, 0); lua_pushcfunction(L, EventCallbackFunctions::luaEventCallbackLoad); - for (auto [value, name] : magic_enum::enum_entries<EventCallback_t>()) { + for (const auto &[value, name] : magic_enum::enum_entries<EventCallback_t>()) { if (value != EventCallback_t::none) { std::string methodName = magic_enum::enum_name(value).data(); lua_pushstring(L, methodName.c_str()); @@ -811,56 +888,56 @@ int GameFunctions::luaGameGetEventCallbacks(lua_State* L) { int GameFunctions::luaGameRegisterAchievement(lua_State* L) { // Game.registerAchievement(id, name, description, secret, grade, points) if (lua_gettop(L) < 6) { - reportErrorFunc("Achievement can only be registered with all params."); + Lua::reportErrorFunc("Achievement can only be registered with all params."); return 1; } - uint16_t id = getNumber<uint16_t>(L, 1); - std::string name = getString(L, 2); - std::string description = getString(L, 3); - bool secret = getBoolean(L, 4); - uint8_t grade = getNumber<uint8_t>(L, 5); - uint8_t points = getNumber<uint8_t>(L, 6); + const uint16_t id = Lua::getNumber<uint16_t>(L, 1); + const std::string name = Lua::getString(L, 2); + const std::string description = Lua::getString(L, 3); + const bool secret = Lua::getBoolean(L, 4); + const uint8_t grade = Lua::getNumber<uint8_t>(L, 5); + const uint8_t points = Lua::getNumber<uint8_t>(L, 6); g_game().registerAchievement(id, name, description, secret, grade, points); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GameFunctions::luaGameGetAchievementInfoById(lua_State* L) { // Game.getAchievementInfoById(id) - uint16_t id = getNumber<uint16_t>(L, 1); - Achievement achievement = g_game().getAchievementById(id); + const uint16_t id = Lua::getNumber<uint16_t>(L, 1); + const Achievement achievement = g_game().getAchievementById(id); if (achievement.id == 0) { - reportErrorFunc("Achievement id is wrong"); + Lua::reportErrorFunc("Achievement id is wrong"); return 1; } lua_createtable(L, 0, 6); - setField(L, "id", achievement.id); - setField(L, "name", achievement.name); - setField(L, "description", achievement.description); - setField(L, "points", achievement.points); - setField(L, "grade", achievement.grade); - setField(L, "secret", achievement.secret); + Lua::setField(L, "id", achievement.id); + Lua::setField(L, "name", achievement.name); + Lua::setField(L, "description", achievement.description); + Lua::setField(L, "points", achievement.points); + Lua::setField(L, "grade", achievement.grade); + Lua::setField(L, "secret", achievement.secret); return 1; } int GameFunctions::luaGameGetAchievementInfoByName(lua_State* L) { // Game.getAchievementInfoByName(name) - std::string name = getString(L, 1); - Achievement achievement = g_game().getAchievementByName(name); + const std::string name = Lua::getString(L, 1); + const Achievement achievement = g_game().getAchievementByName(name); if (achievement.id == 0) { - reportErrorFunc("Achievement name is wrong"); + Lua::reportErrorFunc("Achievement name is wrong"); return 1; } lua_createtable(L, 0, 6); - setField(L, "id", achievement.id); - setField(L, "name", achievement.name); - setField(L, "description", achievement.description); - setField(L, "points", achievement.points); - setField(L, "grade", achievement.grade); - setField(L, "secret", achievement.secret); + Lua::setField(L, "id", achievement.id); + Lua::setField(L, "name", achievement.name); + Lua::setField(L, "description", achievement.description); + Lua::setField(L, "points", achievement.points); + Lua::setField(L, "grade", achievement.grade); + Lua::setField(L, "secret", achievement.secret); return 1; } @@ -871,12 +948,12 @@ int GameFunctions::luaGameGetSecretAchievements(lua_State* L) { lua_createtable(L, achievements.size(), 0); for (const auto &achievement : achievements) { lua_createtable(L, 0, 6); - setField(L, "id", achievement.id); - setField(L, "name", achievement.name); - setField(L, "description", achievement.description); - setField(L, "points", achievement.points); - setField(L, "grade", achievement.grade); - setField(L, "secret", achievement.secret); + Lua::setField(L, "id", achievement.id); + Lua::setField(L, "name", achievement.name); + Lua::setField(L, "description", achievement.description); + Lua::setField(L, "points", achievement.points); + Lua::setField(L, "grade", achievement.grade); + Lua::setField(L, "secret", achievement.secret); lua_rawseti(L, -2, ++index); } return 1; @@ -889,12 +966,12 @@ int GameFunctions::luaGameGetPublicAchievements(lua_State* L) { lua_createtable(L, achievements.size(), 0); for (const auto &achievement : achievements) { lua_createtable(L, 0, 6); - setField(L, "id", achievement.id); - setField(L, "name", achievement.name); - setField(L, "description", achievement.description); - setField(L, "points", achievement.points); - setField(L, "grade", achievement.grade); - setField(L, "secret", achievement.secret); + Lua::setField(L, "id", achievement.id); + Lua::setField(L, "name", achievement.name); + Lua::setField(L, "description", achievement.description); + Lua::setField(L, "points", achievement.points); + Lua::setField(L, "grade", achievement.grade); + Lua::setField(L, "secret", achievement.secret); lua_rawseti(L, -2, ++index); } return 1; @@ -907,12 +984,12 @@ int GameFunctions::luaGameGetAchievements(lua_State* L) { lua_createtable(L, achievements.size(), 0); for (const auto &achievement_it : achievements) { lua_createtable(L, 0, 6); - setField(L, "id", achievement_it.first); - setField(L, "name", achievement_it.second.name); - setField(L, "description", achievement_it.second.description); - setField(L, "points", achievement_it.second.points); - setField(L, "grade", achievement_it.second.grade); - setField(L, "secret", achievement_it.second.secret); + Lua::setField(L, "id", achievement_it.first); + Lua::setField(L, "name", achievement_it.second.name); + Lua::setField(L, "description", achievement_it.second.description); + Lua::setField(L, "points", achievement_it.second.points); + Lua::setField(L, "grade", achievement_it.second.grade); + Lua::setField(L, "secret", achievement_it.second.secret); lua_rawseti(L, -2, ++index); } return 1; diff --git a/src/lua/functions/core/game/game_functions.hpp b/src/lua/functions/core/game/game_functions.hpp index 70e81061c9c..6d332face9f 100644 --- a/src/lua/functions/core/game/game_functions.hpp +++ b/src/lua/functions/core/game/game_functions.hpp @@ -9,87 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class GameFunctions final : LuaScriptInterface { +class GameFunctions { public: - static void init(lua_State* L) { - registerTable(L, "Game"); - - registerMethod(L, "Game", "createNpcType", GameFunctions::luaGameCreateNpcType); - registerMethod(L, "Game", "createMonsterType", GameFunctions::luaGameCreateMonsterType); - - registerMethod(L, "Game", "getSpectators", GameFunctions::luaGameGetSpectators); - - registerMethod(L, "Game", "getBoostedCreature", GameFunctions::luaGameGetBoostedCreature); - registerMethod(L, "Game", "getBestiaryList", GameFunctions::luaGameGetBestiaryList); - - registerMethod(L, "Game", "getPlayers", GameFunctions::luaGameGetPlayers); - registerMethod(L, "Game", "loadMap", GameFunctions::luaGameLoadMap); - registerMethod(L, "Game", "loadMapChunk", GameFunctions::luaGameloadMapChunk); - - registerMethod(L, "Game", "getExperienceForLevel", GameFunctions::luaGameGetExperienceForLevel); - registerMethod(L, "Game", "getMonsterCount", GameFunctions::luaGameGetMonsterCount); - registerMethod(L, "Game", "getPlayerCount", GameFunctions::luaGameGetPlayerCount); - registerMethod(L, "Game", "getNpcCount", GameFunctions::luaGameGetNpcCount); - registerMethod(L, "Game", "getMonsterTypes", GameFunctions::luaGameGetMonsterTypes); - - registerMethod(L, "Game", "getTowns", GameFunctions::luaGameGetTowns); - registerMethod(L, "Game", "getHouses", GameFunctions::luaGameGetHouses); - - registerMethod(L, "Game", "getGameState", GameFunctions::luaGameGetGameState); - registerMethod(L, "Game", "setGameState", GameFunctions::luaGameSetGameState); - - registerMethod(L, "Game", "getWorldType", GameFunctions::luaGameGetWorldType); - registerMethod(L, "Game", "setWorldType", GameFunctions::luaGameSetWorldType); - - registerMethod(L, "Game", "getReturnMessage", GameFunctions::luaGameGetReturnMessage); - - registerMethod(L, "Game", "createItem", GameFunctions::luaGameCreateItem); - registerMethod(L, "Game", "createContainer", GameFunctions::luaGameCreateContainer); - registerMethod(L, "Game", "createMonster", GameFunctions::luaGameCreateMonster); - registerMethod(L, "Game", "createNpc", GameFunctions::luaGameCreateNpc); - registerMethod(L, "Game", "generateNpc", GameFunctions::luaGameGenerateNpc); - registerMethod(L, "Game", "createTile", GameFunctions::luaGameCreateTile); - registerMethod(L, "Game", "createBestiaryCharm", GameFunctions::luaGameCreateBestiaryCharm); - - registerMethod(L, "Game", "createItemClassification", GameFunctions::luaGameCreateItemClassification); - - registerMethod(L, "Game", "getBestiaryCharm", GameFunctions::luaGameGetBestiaryCharm); - - registerMethod(L, "Game", "startRaid", GameFunctions::luaGameStartRaid); - - registerMethod(L, "Game", "getClientVersion", GameFunctions::luaGameGetClientVersion); - - registerMethod(L, "Game", "reload", GameFunctions::luaGameReload); - - registerMethod(L, "Game", "hasDistanceEffect", GameFunctions::luaGameHasDistanceEffect); - registerMethod(L, "Game", "hasEffect", GameFunctions::luaGameHasEffect); - registerMethod(L, "Game", "getOfflinePlayer", GameFunctions::luaGameGetOfflinePlayer); - registerMethod(L, "Game", "getNormalizedPlayerName", GameFunctions::luaGameGetNormalizedPlayerName); - registerMethod(L, "Game", "getNormalizedGuildName", GameFunctions::luaGameGetNormalizedGuildName); - - registerMethod(L, "Game", "addInfluencedMonster", GameFunctions::luaGameAddInfluencedMonster); - registerMethod(L, "Game", "removeInfluencedMonster", GameFunctions::luaGameRemoveInfluencedMonster); - registerMethod(L, "Game", "getInfluencedMonsters", GameFunctions::luaGameGetInfluencedMonsters); - registerMethod(L, "Game", "makeFiendishMonster", GameFunctions::luaGameMakeFiendishMonster); - registerMethod(L, "Game", "removeFiendishMonster", GameFunctions::luaGameRemoveFiendishMonster); - registerMethod(L, "Game", "getFiendishMonsters", GameFunctions::luaGameGetFiendishMonsters); - registerMethod(L, "Game", "getBoostedBoss", GameFunctions::luaGameGetBoostedBoss); - - registerMethod(L, "Game", "getLadderIds", GameFunctions::luaGameGetLadderIds); - registerMethod(L, "Game", "getDummies", GameFunctions::luaGameGetDummies); - - registerMethod(L, "Game", "getTalkActions", GameFunctions::luaGameGetTalkActions); - registerMethod(L, "Game", "getEventCallbacks", GameFunctions::luaGameGetEventCallbacks); - - registerMethod(L, "Game", "registerAchievement", GameFunctions::luaGameRegisterAchievement); - registerMethod(L, "Game", "getAchievementInfoById", GameFunctions::luaGameGetAchievementInfoById); - registerMethod(L, "Game", "getAchievementInfoByName", GameFunctions::luaGameGetAchievementInfoByName); - registerMethod(L, "Game", "getSecretAchievements", GameFunctions::luaGameGetSecretAchievements); - registerMethod(L, "Game", "getPublicAchievements", GameFunctions::luaGameGetPublicAchievements); - registerMethod(L, "Game", "getAchievements", GameFunctions::luaGameGetAchievements); - } + static void init(lua_State* L); private: static int luaGameCreateMonsterType(lua_State* L); diff --git a/src/lua/functions/core/game/global_functions.cpp b/src/lua/functions/core/game/global_functions.cpp index 958c6deb881..6eb21910701 100644 --- a/src/lua/functions/core/game/global_functions.cpp +++ b/src/lua/functions/core/game/global_functions.cpp @@ -7,38 +7,85 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/core/game/global_functions.hpp" + +#include "config/configmanager.hpp" +#include "creatures/creature.hpp" +#include "creatures/combat/condition.hpp" #include "creatures/interactions/chat.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/save_manager.hpp" -#include "lua/functions/core/game/global_functions.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "lua/global/globalevent.hpp" +#include "lua/global/lua_timer_event_descr.hpp" #include "lua/scripts/lua_environment.hpp" #include "lua/scripts/script_environment.hpp" -#include "lua/global/globalevent.hpp" #include "server/network/protocol/protocolstatus.hpp" -#include "creatures/players/wheel/player_wheel.hpp" -#include "lua/global/lua_timer_event_descr.hpp" +#include "lua/functions/lua_functions_loader.hpp" +#include "creatures/players/player.hpp" + +void GlobalFunctions::init(lua_State* L) { + lua_register(L, "addEvent", GlobalFunctions::luaAddEvent); + lua_register(L, "cleanMap", GlobalFunctions::luaCleanMap); + lua_register(L, "createCombatArea", GlobalFunctions::luaCreateCombatArea); + lua_register(L, "debugPrint", GlobalFunctions::luaDebugPrint); + lua_register(L, "doAddContainerItem", GlobalFunctions::luaDoAddContainerItem); + lua_register(L, "doAreaCombatCondition", GlobalFunctions::luaDoAreaCombatCondition); + lua_register(L, "doAreaCombatDispel", GlobalFunctions::luaDoAreaCombatDispel); + lua_register(L, "doAreaCombatHealth", GlobalFunctions::luaDoAreaCombatHealth); + lua_register(L, "doAreaCombatMana", GlobalFunctions::luaDoAreaCombatMana); + lua_register(L, "doChallengeCreature", GlobalFunctions::luaDoChallengeCreature); + lua_register(L, "doPlayerAddItem", GlobalFunctions::luaDoPlayerAddItem); + lua_register(L, "doTargetCombatCondition", GlobalFunctions::luaDoTargetCombatCondition); + lua_register(L, "doTargetCombatDispel", GlobalFunctions::luaDoTargetCombatDispel); + lua_register(L, "doTargetCombatHealth", GlobalFunctions::luaDoTargetCombatHealth); + lua_register(L, "doTargetCombatMana", GlobalFunctions::luaDoTargetCombatMana); + lua_register(L, "getDepotId", GlobalFunctions::luaGetDepotId); + lua_register(L, "getWaypointPositionByName", GlobalFunctions::luaGetWaypointPositionByName); + lua_register(L, "getWorldLight", GlobalFunctions::luaGetWorldLight); + lua_register(L, "getWorldTime", GlobalFunctions::luaGetWorldTime); + lua_register(L, "getWorldUpTime", GlobalFunctions::luaGetWorldUpTime); + lua_register(L, "isDepot", GlobalFunctions::luaIsDepot); + lua_register(L, "isInWar", GlobalFunctions::luaIsInWar); + lua_register(L, "isMovable", GlobalFunctions::luaIsMovable); + lua_register(L, "isValidUID", GlobalFunctions::luaIsValidUID); + lua_register(L, "saveServer", GlobalFunctions::luaSaveServer); + lua_register(L, "sendChannelMessage", GlobalFunctions::luaSendChannelMessage); + lua_register(L, "sendGuildChannelMessage", GlobalFunctions::luaSendGuildChannelMessage); + lua_register(L, "stopEvent", GlobalFunctions::luaStopEvent); + + Lua::registerGlobalVariable(L, "INDEX_WHEREEVER", INDEX_WHEREEVER); + Lua::registerGlobalBoolean(L, "VIRTUAL_PARENT", true); + Lua::registerGlobalMethod(L, "isType", GlobalFunctions::luaIsType); + Lua::registerGlobalMethod(L, "rawgetmetatable", GlobalFunctions::luaRawGetMetatable); + Lua::registerGlobalMethod(L, "createTable", GlobalFunctions::luaCreateTable); + Lua::registerGlobalMethod(L, "systemTime", GlobalFunctions::luaSystemTime); + Lua::registerGlobalMethod(L, "getFormattedTimeRemaining", GlobalFunctions::luaGetFormattedTimeRemaining); + Lua::registerGlobalMethod(L, "reportError", GlobalFunctions::luaReportError); +} -class Creature; int GlobalFunctions::luaDoPlayerAddItem(lua_State* L) { // doPlayerAddItem(cid, itemid, <optional: default: 1> count/subtype, <optional: default: 1> canDropOnMap) // doPlayerAddItem(cid, itemid, <optional: default: 1> count, <optional: default: 1> canDropOnMap, <optional: default: 1>subtype) - std::shared_ptr<Player> player = getPlayer(L, 1); + const auto &player = Lua::getPlayer(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint16_t itemId = getNumber<uint16_t>(L, 2); - int32_t count = getNumber<int32_t>(L, 3, 1); - bool canDropOnMap = getBoolean(L, 4, true); - uint16_t subType = getNumber<uint16_t>(L, 5, 1); + const uint16_t itemId = Lua::getNumber<uint16_t>(L, 2); + const auto count = Lua::getNumber<int32_t>(L, 3, 1); + const bool canDropOnMap = Lua::getBoolean(L, 4, true); + auto subType = Lua::getNumber<uint16_t>(L, 5, 1); const ItemType &it = Item::items[itemId]; int32_t itemCount; - auto parameters = lua_gettop(L); + const auto parameters = lua_gettop(L); if (parameters > 4) { // subtype already supplied, count then is the amount itemCount = std::max<int32_t>(1, count); @@ -59,10 +106,10 @@ int GlobalFunctions::luaDoPlayerAddItem(lua_State* L) { stackCount = it.stackSize; } - std::shared_ptr<Item> newItem = Item::CreateItem(itemId, stackCount); + const auto &newItem = Item::CreateItem(itemId, stackCount); if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -72,66 +119,66 @@ int GlobalFunctions::luaDoPlayerAddItem(lua_State* L) { ReturnValue ret = g_game().internalPlayerAddItem(player, newItem, canDropOnMap); if (ret != RETURNVALUE_NOERROR) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } if (--itemCount == 0) { if (newItem->getParent()) { - uint32_t uid = getScriptEnv()->addThing(newItem); + const uint32_t uid = Lua::getScriptEnv()->addThing(newItem); lua_pushnumber(L, uid); return 1; } else { // stackable item stacked with existing object, newItem will be released - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } } } - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } int GlobalFunctions::luaIsValidUID(lua_State* L) { // isValidUID(uid) - pushBoolean(L, getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1)) != nullptr); + Lua::pushBoolean(L, Lua::getScriptEnv()->getThingByUID(Lua::getNumber<uint32_t>(L, -1)) != nullptr); return 1; } int GlobalFunctions::luaIsDepot(lua_State* L) { // isDepot(uid) - std::shared_ptr<Container> container = getScriptEnv()->getContainerByUID(getNumber<uint32_t>(L, -1)); - pushBoolean(L, container && container->getDepotLocker()); + const auto &container = Lua::getScriptEnv()->getContainerByUID(Lua::getNumber<uint32_t>(L, -1)); + Lua::pushBoolean(L, container && container->getDepotLocker()); return 1; } int GlobalFunctions::luaIsMovable(lua_State* L) { // isMovable(uid) // isMovable(uid) - std::shared_ptr<Thing> thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1)); - pushBoolean(L, thing && thing->isPushable()); + const auto &thing = Lua::getScriptEnv()->getThingByUID(Lua::getNumber<uint32_t>(L, -1)); + Lua::pushBoolean(L, thing && thing->isPushable()); return 1; } int GlobalFunctions::luaDoAddContainerItem(lua_State* L) { // doAddContainerItem(uid, itemid, <optional> count/subtype) - uint32_t uid = getNumber<uint32_t>(L, 1); + const uint32_t uid = Lua::getNumber<uint32_t>(L, 1); - ScriptEnvironment* env = getScriptEnv(); - std::shared_ptr<Container> container = env->getContainerByUID(uid); + ScriptEnvironment* env = Lua::getScriptEnv(); + const auto &container = env->getContainerByUID(uid); if (!container) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint16_t itemId = getNumber<uint16_t>(L, 2); + const uint16_t itemId = Lua::getNumber<uint16_t>(L, 2); const ItemType &it = Item::items[itemId]; int32_t itemCount = 1; int32_t subType = 1; - uint32_t count = getNumber<uint32_t>(L, 3, 1); + const auto count = Lua::getNumber<uint32_t>(L, 3, 1); if (it.hasSubType()) { if (it.stackable) { @@ -144,11 +191,11 @@ int GlobalFunctions::luaDoAddContainerItem(lua_State* L) { } while (itemCount > 0) { - int32_t stackCount = std::min<int32_t>(it.stackSize, subType); - std::shared_ptr<Item> newItem = Item::CreateItem(itemId, stackCount); + const int32_t stackCount = std::min<int32_t>(it.stackSize, subType); + const auto &newItem = Item::CreateItem(itemId, stackCount); if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -158,7 +205,7 @@ int GlobalFunctions::luaDoAddContainerItem(lua_State* L) { ReturnValue ret = g_game().internalAddItem(container, newItem); if (ret != RETURNVALUE_NOERROR) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -167,31 +214,31 @@ int GlobalFunctions::luaDoAddContainerItem(lua_State* L) { lua_pushnumber(L, env->addThing(newItem)); } else { // stackable item stacked with existing object, newItem will be released - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } } - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } int GlobalFunctions::luaGetDepotId(lua_State* L) { // getDepotId(uid) - uint32_t uid = getNumber<uint32_t>(L, -1); + const uint32_t uid = Lua::getNumber<uint32_t>(L, -1); - std::shared_ptr<Container> container = getScriptEnv()->getContainerByUID(uid); + const auto &container = Lua::getScriptEnv()->getContainerByUID(uid); if (!container) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<DepotLocker> depotLocker = container->getDepotLocker(); + const auto &depotLocker = container->getDepotLocker(); if (!depotLocker) { - reportErrorFunc("Depot not found"); - pushBoolean(L, false); + Lua::reportErrorFunc("Depot not found"); + Lua::pushBoolean(L, false); return 1; } @@ -201,14 +248,14 @@ int GlobalFunctions::luaGetDepotId(lua_State* L) { int GlobalFunctions::luaGetWorldTime(lua_State* L) { // getWorldTime() - uint32_t time = g_game().getLightHour(); + const uint32_t time = g_game().getLightHour(); lua_pushnumber(L, time); return 1; } int GlobalFunctions::luaGetWorldLight(lua_State* L) { // getWorldLight() - LightInfo lightInfo = g_game().getWorldLightInfo(); + const LightInfo lightInfo = g_game().getWorldLightInfo(); lua_pushnumber(L, lightInfo.level); lua_pushnumber(L, lightInfo.color); return 2; @@ -216,30 +263,30 @@ int GlobalFunctions::luaGetWorldLight(lua_State* L) { int GlobalFunctions::luaGetWorldUpTime(lua_State* L) { // getWorldUpTime() - uint64_t uptime = (OTSYS_TIME(true) - ProtocolStatus::start) / 1000; + const uint64_t uptime = (OTSYS_TIME(true) - ProtocolStatus::start) / 1000; lua_pushnumber(L, uptime); return 1; } int GlobalFunctions::luaCreateCombatArea(lua_State* L) { // createCombatArea( {area}, <optional> {extArea} ) - ScriptEnvironment* env = getScriptEnv(); + const ScriptEnvironment* env = Lua::getScriptEnv(); if (env->getScriptId() != EVENT_ID_LOADING) { - reportErrorFunc("This function can only be used while loading the script."); - pushBoolean(L, false); + Lua::reportErrorFunc("This function can only be used while loading the script."); + Lua::pushBoolean(L, false); return 1; } - uint32_t areaId = g_luaEnvironment().createAreaObject(env->getScriptInterface()); + const uint32_t areaId = g_luaEnvironment().createAreaObject(env->getScriptInterface()); const auto &area = g_luaEnvironment().getAreaObject(areaId); - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); if (parameters >= 2) { uint32_t rowsExtArea; std::list<uint32_t> listExtArea; - if (!isTable(L, 2) || !getArea(L, listExtArea, rowsExtArea)) { - reportErrorFunc("Invalid extended area table."); - pushBoolean(L, false); + if (!Lua::isTable(L, 2) || !getArea(L, listExtArea, rowsExtArea)) { + Lua::reportErrorFunc("Invalid extended area table."); + Lua::pushBoolean(L, false); return 1; } area->setupExtArea(listExtArea, rowsExtArea); @@ -247,9 +294,9 @@ int GlobalFunctions::luaCreateCombatArea(lua_State* L) { uint32_t rowsArea = 0; std::list<uint32_t> listArea; - if (!isTable(L, 1) || !getArea(L, listArea, rowsArea)) { - reportErrorFunc("Invalid area table."); - pushBoolean(L, false); + if (!Lua::isTable(L, 1) || !getArea(L, listArea, rowsArea)) { + Lua::reportErrorFunc("Invalid area table."); + Lua::pushBoolean(L, false); return 1; } @@ -260,75 +307,75 @@ int GlobalFunctions::luaCreateCombatArea(lua_State* L) { int GlobalFunctions::luaDoAreaCombatHealth(lua_State* L) { // doAreaCombatHealth(cid, type, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint32_t areaId = getNumber<uint32_t>(L, 4); + const uint32_t areaId = Lua::getNumber<uint32_t>(L, 4); const auto &area = g_luaEnvironment().getAreaObject(areaId); if (area || areaId == 0) { - CombatType_t combatType = getNumber<CombatType_t>(L, 2); + const CombatType_t combatType = Lua::getNumber<CombatType_t>(L, 2); CombatParams params; params.combatType = combatType; - params.impactEffect = getNumber<uint16_t>(L, 7); + params.impactEffect = Lua::getNumber<uint16_t>(L, 7); CombatDamage damage; - damage.origin = getNumber<CombatOrigin>(L, 8, ORIGIN_SPELL); + damage.origin = Lua::getNumber<CombatOrigin>(L, 8, ORIGIN_SPELL); damage.primary.type = combatType; - damage.primary.value = normal_random(getNumber<int32_t>(L, 6), getNumber<int32_t>(L, 5)); + damage.primary.value = normal_random(Lua::getNumber<int32_t>(L, 6), Lua::getNumber<int32_t>(L, 5)); - damage.instantSpellName = getString(L, 9); - damage.runeSpellName = getString(L, 10); + damage.instantSpellName = Lua::getString(L, 9); + damage.runeSpellName = Lua::getString(L, 10); if (creature) { - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->wheel()->getCombatDataSpell(damage); } } - Combat::doCombatHealth(creature, getPosition(L, 3), area, damage, params); - pushBoolean(L, true); + Combat::doCombatHealth(creature, Lua::getPosition(L, 3), area, damage, params); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int GlobalFunctions::luaDoTargetCombatHealth(lua_State* L) { // doTargetCombatHealth(cid, target, type, min, max, effect[, origin = ORIGIN_SPELL]) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Creature> target = getCreature(L, 2); + const auto &target = Lua::getCreature(L, 2); if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - CombatType_t combatType = getNumber<CombatType_t>(L, 3); + const CombatType_t combatType = Lua::getNumber<CombatType_t>(L, 3); CombatParams params; params.combatType = combatType; - params.impactEffect = getNumber<uint16_t>(L, 6); + params.impactEffect = Lua::getNumber<uint16_t>(L, 6); CombatDamage damage; - damage.origin = getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL); + damage.origin = Lua::getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL); damage.primary.type = combatType; - damage.primary.value = normal_random(getNumber<int32_t>(L, 4), getNumber<int32_t>(L, 5)); + damage.primary.value = normal_random(Lua::getNumber<int32_t>(L, 4), Lua::getNumber<int32_t>(L, 5)); - damage.instantSpellName = getString(L, 9); - damage.runeSpellName = getString(L, 10); + damage.instantSpellName = Lua::getString(L, 9); + damage.runeSpellName = Lua::getString(L, 10); if (creature) { - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->wheel()->getCombatDataSpell(damage); } } @@ -339,220 +386,220 @@ int GlobalFunctions::luaDoTargetCombatHealth(lua_State* L) { } Combat::doCombatHealth(creature, target, damage, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaDoAreaCombatMana(lua_State* L) { // doAreaCombatMana(cid, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint32_t areaId = getNumber<uint32_t>(L, 3); + const uint32_t areaId = Lua::getNumber<uint32_t>(L, 3); const auto &area = g_luaEnvironment().getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; - params.impactEffect = getNumber<uint16_t>(L, 6); + params.impactEffect = Lua::getNumber<uint16_t>(L, 6); CombatDamage damage; - damage.origin = getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL); + damage.origin = Lua::getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL); damage.primary.type = COMBAT_MANADRAIN; - damage.primary.value = normal_random(getNumber<int32_t>(L, 4), getNumber<int32_t>(L, 5)); + damage.primary.value = normal_random(Lua::getNumber<int32_t>(L, 4), Lua::getNumber<int32_t>(L, 5)); - damage.instantSpellName = getString(L, 8); - damage.runeSpellName = getString(L, 9); + damage.instantSpellName = Lua::getString(L, 8); + damage.runeSpellName = Lua::getString(L, 9); if (creature) { - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->wheel()->getCombatDataSpell(damage); } } - Position pos = getPosition(L, 2); + const Position pos = Lua::getPosition(L, 2); Combat::doCombatMana(creature, pos, area, damage, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int GlobalFunctions::luaDoTargetCombatMana(lua_State* L) { // doTargetCombatMana(cid, target, min, max, effect[, origin = ORIGIN_SPELL) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Creature> target = getCreature(L, 2); + const auto &target = Lua::getCreature(L, 2); if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } CombatParams params; - auto minval = getNumber<int32_t>(L, 3); - auto maxval = getNumber<int32_t>(L, 4); + const auto minval = Lua::getNumber<int32_t>(L, 3); + const auto maxval = Lua::getNumber<int32_t>(L, 4); params.aggressive = minval + maxval < 0; - params.impactEffect = getNumber<uint16_t>(L, 5); + params.impactEffect = Lua::getNumber<uint16_t>(L, 5); CombatDamage damage; - damage.origin = getNumber<CombatOrigin>(L, 6, ORIGIN_SPELL); + damage.origin = Lua::getNumber<CombatOrigin>(L, 6, ORIGIN_SPELL); damage.primary.type = COMBAT_MANADRAIN; damage.primary.value = normal_random(minval, maxval); - damage.instantSpellName = getString(L, 7); - damage.runeSpellName = getString(L, 8); + damage.instantSpellName = Lua::getString(L, 7); + damage.runeSpellName = Lua::getString(L, 8); if (creature) { - if (auto player = creature->getPlayer()) { + if (const auto &player = creature->getPlayer()) { player->wheel()->getCombatDataSpell(damage); } } Combat::doCombatMana(creature, target, damage, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaDoAreaCombatCondition(lua_State* L) { // doAreaCombatCondition(cid, pos, area, condition, effect) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 4); + const auto &condition = Lua::getUserdataShared<Condition>(L, 4); if (!condition) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint32_t areaId = getNumber<uint32_t>(L, 3); + const uint32_t areaId = Lua::getNumber<uint32_t>(L, 3); const auto &area = g_luaEnvironment().getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; - params.impactEffect = getNumber<uint16_t>(L, 5); + params.impactEffect = Lua::getNumber<uint16_t>(L, 5); params.conditionList.emplace_back(condition); - Combat::doCombatCondition(creature, getPosition(L, 2), area, params); - pushBoolean(L, true); + Combat::doCombatCondition(creature, Lua::getPosition(L, 2), area, params); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int GlobalFunctions::luaDoTargetCombatCondition(lua_State* L) { // doTargetCombatCondition(cid, target, condition, effect) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Creature> target = getCreature(L, 2); + const auto &target = Lua::getCreature(L, 2); if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 3); + const auto &condition = Lua::getUserdataShared<Condition>(L, 3); if (!condition) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } CombatParams params; - params.impactEffect = getNumber<uint16_t>(L, 4); + params.impactEffect = Lua::getNumber<uint16_t>(L, 4); params.conditionList.emplace_back(condition->clone()); Combat::doCombatCondition(creature, target, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaDoAreaCombatDispel(lua_State* L) { // doAreaCombatDispel(cid, pos, area, type, effect) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint32_t areaId = getNumber<uint32_t>(L, 3); + const uint32_t areaId = Lua::getNumber<uint32_t>(L, 3); const auto &area = g_luaEnvironment().getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; - params.impactEffect = getNumber<uint16_t>(L, 5); - params.dispelType = getNumber<ConditionType_t>(L, 4); - Combat::doCombatDispel(creature, getPosition(L, 2), area, params); + params.impactEffect = Lua::getNumber<uint16_t>(L, 5); + params.dispelType = Lua::getNumber<ConditionType_t>(L, 4); + Combat::doCombatDispel(creature, Lua::getPosition(L, 2), area, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int GlobalFunctions::luaDoTargetCombatDispel(lua_State* L) { // doTargetCombatDispel(cid, target, type, effect) - std::shared_ptr<Creature> creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + const auto &creature = Lua::getCreature(L, 1); + if (!creature && (!Lua::isNumber(L, 1) || Lua::getNumber<uint32_t>(L, 1) != 0)) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Creature> target = getCreature(L, 2); + const auto &target = Lua::getCreature(L, 2); if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } CombatParams params; - params.dispelType = getNumber<ConditionType_t>(L, 3); - params.impactEffect = getNumber<uint16_t>(L, 4); + params.dispelType = Lua::getNumber<ConditionType_t>(L, 3); + params.impactEffect = Lua::getNumber<uint16_t>(L, 4); Combat::doCombatDispel(creature, target, params); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaDoChallengeCreature(lua_State* L) { // doChallengeCreature(cid, target, targetChangeCooldown) - std::shared_ptr<Creature> creature = getCreature(L, 1); + const auto &creature = Lua::getCreature(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Creature> target = getCreature(L, 2); + const auto &target = Lua::getCreature(L, 2); if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - int targetChangeCooldown = getNumber<int32_t>(L, 3, 6000); + const int targetChangeCooldown = Lua::getNumber<int32_t>(L, 3, 6000); // This function must be defined to take and handle the targetChangeCooldown. target->challengeCreature(creature, targetChangeCooldown); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -560,17 +607,17 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { // addEvent(callback, delay, ...) lua_State* globalState = g_luaEnvironment().getLuaState(); if (!globalState) { - reportErrorFunc("No valid script interface!"); - pushBoolean(L, false); + Lua::reportErrorFunc("No valid script interface!"); + Lua::pushBoolean(L, false); return 1; } else if (globalState != L) { lua_xmove(L, globalState, lua_gettop(L)); } - int parameters = lua_gettop(globalState); - if (!isFunction(globalState, -parameters)) { // -parameters means the first parameter from left to right - reportErrorFunc("callback parameter should be a function."); - pushBoolean(L, false); + const int parameters = lua_gettop(globalState); + if (!Lua::isFunction(globalState, -parameters)) { // -parameters means the first parameter from left to right + Lua::reportErrorFunc("callback parameter should be a function."); + Lua::pushBoolean(L, false); return 1; } @@ -582,9 +629,9 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { } lua_rawgeti(L, -1, 't'); - LuaData_t type = getNumber<LuaData_t>(L, -1); + LuaData_t type = Lua::getNumber<LuaData_t>(L, -1); if (type != LuaData_t::Unknown && type <= LuaData_t::Npc) { - indexes.push_back({ i, type }); + indexes.emplace_back(i, type); } lua_pop(globalState, 2); } @@ -616,7 +663,7 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { warningString += " is unsafe"; } - reportErrorFunc(warningString); + Lua::reportErrorFunc(warningString); } if (g_configManager().getBoolean(CONVERT_UNSAFE_SCRIPTS)) { @@ -653,12 +700,12 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { eventDesc.parameters.push_back(luaL_ref(globalState, LUA_REGISTRYINDEX)); } - uint32_t delay = std::max<uint32_t>(100, getNumber<uint32_t>(globalState, 2)); + const uint32_t delay = std::max<uint32_t>(100, Lua::getNumber<uint32_t>(globalState, 2)); lua_pop(globalState, 1); eventDesc.function = luaL_ref(globalState, LUA_REGISTRYINDEX); - eventDesc.scriptId = getScriptEnv()->getScriptId(); - eventDesc.scriptName = getScriptEnv()->getScriptInterface()->getLoadingScriptName(); + eventDesc.scriptId = Lua::getScriptEnv()->getScriptId(); + eventDesc.scriptName = Lua::getScriptEnv()->getScriptInterface()->getLoadingScriptName(); auto &lastTimerEventId = g_luaEnvironment().lastEventTimerId; eventDesc.eventId = g_dispatcher().scheduleEvent( @@ -667,7 +714,7 @@ int GlobalFunctions::luaAddEvent(lua_State* L) { "LuaEnvironment::executeTimerEvent" ); - g_luaEnvironment().timerEvents.emplace(lastTimerEventId, std::move(eventDesc)); + g_luaEnvironment().timerEvents.try_emplace(lastTimerEventId, std::move(eventDesc)); lua_pushnumber(L, lastTimerEventId++); return 1; } @@ -676,38 +723,38 @@ int GlobalFunctions::luaStopEvent(lua_State* L) { // stopEvent(eventid) lua_State* globalState = g_luaEnvironment().getLuaState(); if (!globalState) { - reportErrorFunc("No valid script interface!"); - pushBoolean(L, false); + Lua::reportErrorFunc("No valid script interface!"); + Lua::pushBoolean(L, false); return 1; } - uint32_t eventId = getNumber<uint32_t>(L, 1); + const uint32_t eventId = Lua::getNumber<uint32_t>(L, 1); auto &timerEvents = g_luaEnvironment().timerEvents; - auto it = timerEvents.find(eventId); + const auto it = timerEvents.find(eventId); if (it == timerEvents.end()) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - LuaTimerEventDesc timerEventDesc = std::move(it->second); + const LuaTimerEventDesc timerEventDesc = std::move(it->second); timerEvents.erase(it); g_dispatcher().stopEvent(timerEventDesc.eventId); luaL_unref(globalState, LUA_REGISTRYINDEX, timerEventDesc.function); - for (auto parameter : timerEventDesc.parameters) { + for (const auto parameter : timerEventDesc.parameters) { luaL_unref(globalState, LUA_REGISTRYINDEX, parameter); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaSaveServer(lua_State* L) { g_globalEvents().save(); g_saveManager().scheduleAll(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -718,27 +765,27 @@ int GlobalFunctions::luaCleanMap(lua_State* L) { int GlobalFunctions::luaDebugPrint(lua_State* L) { // debugPrint(text) - reportErrorFunc(getString(L, -1)); + Lua::reportErrorFunc(Lua::getString(L, -1)); return 0; } int GlobalFunctions::luaIsInWar(lua_State* L) { // isInWar(cid, target) - const auto &player = getPlayer(L, 1); + const auto &player = Lua::getPlayer(L, 1); if (!player) { - reportErrorFunc(fmt::format("{} - Player", getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); - pushBoolean(L, false); + Lua::reportErrorFunc(fmt::format("{} - Player", Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); + Lua::pushBoolean(L, false); return 1; } - const auto &targetPlayer = getPlayer(L, 2); + const auto &targetPlayer = Lua::getPlayer(L, 2); if (!targetPlayer) { - reportErrorFunc(fmt::format("{} - TargetPlayer", getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); - pushBoolean(L, false); + Lua::reportErrorFunc(fmt::format("{} - TargetPlayer", Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, player->isInWar(targetPlayer)); + Lua::pushBoolean(L, player->isInWar(targetPlayer)); return 1; } @@ -746,44 +793,44 @@ int GlobalFunctions::luaGetWaypointPositionByName(lua_State* L) { // getWaypointPositionByName(name) auto &waypoints = g_game().map.waypoints; - auto it = waypoints.find(getString(L, -1)); + const auto it = waypoints.find(Lua::getString(L, -1)); if (it != waypoints.end()) { - pushPosition(L, it->second); + Lua::pushPosition(L, it->second); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int GlobalFunctions::luaSendChannelMessage(lua_State* L) { // sendChannelMessage(channelId, type, message) - uint16_t channelId = getNumber<uint16_t>(L, 1); + const uint16_t channelId = Lua::getNumber<uint16_t>(L, 1); const auto &channel = g_chat().getChannelById(channelId); if (!channel) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - SpeakClasses type = getNumber<SpeakClasses>(L, 2); - std::string message = getString(L, 3); + const SpeakClasses type = Lua::getNumber<SpeakClasses>(L, 2); + const std::string message = Lua::getString(L, 3); channel->sendToAll(message, type); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GlobalFunctions::luaSendGuildChannelMessage(lua_State* L) { // sendGuildChannelMessage(guildId, type, message) - uint32_t guildId = getNumber<uint32_t>(L, 1); + const uint32_t guildId = Lua::getNumber<uint32_t>(L, 1); const auto &channel = g_chat().getGuildChannelById(guildId); if (!channel) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - SpeakClasses type = getNumber<SpeakClasses>(L, 2); - std::string message = getString(L, 3); + const SpeakClasses type = Lua::getNumber<SpeakClasses>(L, 2); + const std::string message = Lua::getString(L, 3); channel->sendToAll(message, type); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -793,34 +840,34 @@ int GlobalFunctions::luaIsType(lua_State* L) { lua_getmetatable(L, -2); lua_rawgeti(L, -2, 'p'); - uint_fast8_t parentsB = getNumber<uint_fast8_t>(L, 1); + const uint_fast8_t parentsB = Lua::getNumber<uint_fast8_t>(L, 1); lua_rawgeti(L, -3, 'h'); - size_t hashB = getNumber<size_t>(L, 1); + const size_t hashB = Lua::getNumber<size_t>(L, 1); lua_rawgeti(L, -3, 'p'); - uint_fast8_t parentsA = getNumber<uint_fast8_t>(L, 1); + const uint_fast8_t parentsA = Lua::getNumber<uint_fast8_t>(L, 1); for (uint_fast8_t i = parentsA; i < parentsB; ++i) { lua_getfield(L, -3, "__index"); lua_replace(L, -4); } lua_rawgeti(L, -4, 'h'); - size_t hashA = getNumber<size_t>(L, 1); + const size_t hashA = Lua::getNumber<size_t>(L, 1); - pushBoolean(L, hashA == hashB); + Lua::pushBoolean(L, hashA == hashB); return 1; } int GlobalFunctions::luaRawGetMetatable(lua_State* L) { // rawgetmetatable(metatableName) - luaL_getmetatable(L, getString(L, 1).c_str()); + luaL_getmetatable(L, Lua::getString(L, 1).c_str()); return 1; } int GlobalFunctions::luaCreateTable(lua_State* L) { // createTable(arrayLength, keyLength) - lua_createtable(L, getNumber<int32_t>(L, 1), getNumber<int32_t>(L, 2)); + lua_createtable(L, Lua::getNumber<int32_t>(L, 1), Lua::getNumber<int32_t>(L, 2)); return 1; } @@ -832,31 +879,31 @@ int GlobalFunctions::luaSystemTime(lua_State* L) { int GlobalFunctions::luaGetFormattedTimeRemaining(lua_State* L) { // getFormattedTimeRemaining(time) - time_t time = getNumber<uint32_t>(L, 1); + const time_t time = Lua::getNumber<uint32_t>(L, 1); lua_pushstring(L, getFormattedTimeRemaining(time).c_str()); return 1; } int GlobalFunctions::luaReportError(lua_State* L) { // reportError(errorDescription) - auto errorDescription = getString(L, 1); - reportError(__func__, errorDescription, true); + const auto errorDescription = Lua::getString(L, 1); + Lua::reportError(__func__, errorDescription, true); return 1; } bool GlobalFunctions::getArea(lua_State* L, std::list<uint32_t> &list, uint32_t &rows) { lua_pushnil(L); for (rows = 0; lua_next(L, -2) != 0; ++rows) { - if (!isTable(L, -1)) { + if (!Lua::isTable(L, -1)) { return false; } lua_pushnil(L); while (lua_next(L, -2) != 0) { - if (!isNumber(L, -1)) { + if (!Lua::isNumber(L, -1)) { return false; } - list.push_back(getNumber<uint32_t>(L, -1)); + list.push_back(Lua::getNumber<uint32_t>(L, -1)); lua_pop(L, 1); } diff --git a/src/lua/functions/core/game/global_functions.hpp b/src/lua/functions/core/game/global_functions.hpp index cef752c6695..7ed0c177c88 100644 --- a/src/lua/functions/core/game/global_functions.hpp +++ b/src/lua/functions/core/game/global_functions.hpp @@ -9,49 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class GlobalFunctions final : LuaScriptInterface { +class GlobalFunctions { public: - static void init(lua_State* L) { - lua_register(L, "addEvent", GlobalFunctions::luaAddEvent); - lua_register(L, "cleanMap", GlobalFunctions::luaCleanMap); - lua_register(L, "createCombatArea", GlobalFunctions::luaCreateCombatArea); - lua_register(L, "debugPrint", GlobalFunctions::luaDebugPrint); - lua_register(L, "doAddContainerItem", GlobalFunctions::luaDoAddContainerItem); - lua_register(L, "doAreaCombatCondition", GlobalFunctions::luaDoAreaCombatCondition); - lua_register(L, "doAreaCombatDispel", GlobalFunctions::luaDoAreaCombatDispel); - lua_register(L, "doAreaCombatHealth", GlobalFunctions::luaDoAreaCombatHealth); - lua_register(L, "doAreaCombatMana", GlobalFunctions::luaDoAreaCombatMana); - lua_register(L, "doChallengeCreature", GlobalFunctions::luaDoChallengeCreature); - lua_register(L, "doPlayerAddItem", GlobalFunctions::luaDoPlayerAddItem); - lua_register(L, "doTargetCombatCondition", GlobalFunctions::luaDoTargetCombatCondition); - lua_register(L, "doTargetCombatDispel", GlobalFunctions::luaDoTargetCombatDispel); - lua_register(L, "doTargetCombatHealth", GlobalFunctions::luaDoTargetCombatHealth); - lua_register(L, "doTargetCombatMana", GlobalFunctions::luaDoTargetCombatMana); - lua_register(L, "getDepotId", GlobalFunctions::luaGetDepotId); - lua_register(L, "getWaypointPositionByName", GlobalFunctions::luaGetWaypointPositionByName); - lua_register(L, "getWorldLight", GlobalFunctions::luaGetWorldLight); - lua_register(L, "getWorldTime", GlobalFunctions::luaGetWorldTime); - lua_register(L, "getWorldUpTime", GlobalFunctions::luaGetWorldUpTime); - lua_register(L, "isDepot", GlobalFunctions::luaIsDepot); - lua_register(L, "isInWar", GlobalFunctions::luaIsInWar); - lua_register(L, "isMovable", GlobalFunctions::luaIsMovable); - lua_register(L, "isValidUID", GlobalFunctions::luaIsValidUID); - lua_register(L, "saveServer", GlobalFunctions::luaSaveServer); - lua_register(L, "sendChannelMessage", GlobalFunctions::luaSendChannelMessage); - lua_register(L, "sendGuildChannelMessage", GlobalFunctions::luaSendGuildChannelMessage); - lua_register(L, "stopEvent", GlobalFunctions::luaStopEvent); - - registerGlobalVariable(L, "INDEX_WHEREEVER", INDEX_WHEREEVER); - registerGlobalBoolean(L, "VIRTUAL_PARENT", true); - registerGlobalMethod(L, "isType", GlobalFunctions::luaIsType); - registerGlobalMethod(L, "rawgetmetatable", GlobalFunctions::luaRawGetMetatable); - registerGlobalMethod(L, "createTable", GlobalFunctions::luaCreateTable); - registerGlobalMethod(L, "systemTime", GlobalFunctions::luaSystemTime); - registerGlobalMethod(L, "getFormattedTimeRemaining", GlobalFunctions::luaGetFormattedTimeRemaining); - registerGlobalMethod(L, "reportError", GlobalFunctions::luaReportError); - } + static void init(lua_State* L); private: static int luaAddEvent(lua_State* L); diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp index a0870052f87..2136a3e5927 100644 --- a/src/lua/functions/core/game/lua_enums.cpp +++ b/src/lua/functions/core/game/lua_enums.cpp @@ -9,15 +9,13 @@ #include "lua/functions/core/game/lua_enums.hpp" -#include "creatures/players/wheel/wheel_gems.hpp" #include "creatures/players/wheel/wheel_definitions.hpp" -#include "io/io_bosstiary.hpp" -#include "config/configmanager.hpp" -#include "creatures/creature.hpp" -#include "declarations.hpp" -#include "game/functions/game_reload.hpp" -#include "enums/account_type.hpp" #include "enums/account_group_type.hpp" +#include "enums/account_type.hpp" +#include "enums/item_attribute.hpp" +#include "game/functions/game_reload.hpp" +#include "io/io_bosstiary.hpp" +#include "lua/functions/lua_functions_loader.hpp" constexpr const char* soundNamespace = "SOUND_EFFECT_TYPE_"; @@ -25,7 +23,7 @@ constexpr const char* soundNamespace = "SOUND_EFFECT_TYPE_"; { \ auto number = magic_enum::enum_integer(enumClassType); \ auto name = magic_enum::enum_name(enumClassType).data(); \ - registerGlobalVariable(luaState, name, number); \ + Lua::registerGlobalVariable(luaState, name, number); \ } \ void(0) @@ -33,15 +31,15 @@ constexpr const char* soundNamespace = "SOUND_EFFECT_TYPE_"; { \ auto number = magic_enum::enum_integer(enumClassType); \ auto name = std::string(luaNamespace) + magic_enum::enum_name(enumClassType).data(); \ - registerGlobalVariable(luaState, name, number); \ + Lua::registerGlobalVariable(luaState, name, number); \ } \ void(0) -#define registerEnum(L, value) \ - { \ - std::string enumName = #value; \ - registerGlobalVariable(L, enumName.substr(enumName.find_last_of(':') + 1), value); \ - } \ +#define registerEnum(L, value) \ + { \ + std::string enumName = #value; \ + Lua::registerGlobalVariable(L, enumName.substr(enumName.find_last_of(':') + 1), value); \ + } \ void(0) /** @@ -58,7 +56,7 @@ is "SILENCE", the registered full name will be "SOUND_EFFECT_TYPE_SILENCE". { \ std::string enumName = #enumValue; \ std::string enumNameWithNamespace = std::string(luaNamespace) + std::string(enumName.substr(enumName.find_last_of(':') + 1)); \ - registerGlobalVariable(L, enumNameWithNamespace, enumValue); \ + Lua::registerGlobalVariable(L, enumNameWithNamespace, enumValue); \ } \ void(0) @@ -334,7 +332,7 @@ void LuaEnums::initFactionEnums(lua_State* L) { } void LuaEnums::initConditionEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<ConditionType_t>()) { + for (const auto value : magic_enum::enum_values<ConditionType_t>()) { registerMagicEnum(L, value); } } @@ -795,7 +793,7 @@ void LuaEnums::initItemAttributeEnums(lua_State* L) { auto number = magic_enum::enum_integer(value); // Creation of the "ITEM_ATTRIBUTE_" namespace for lua scripts std::string enumName = "ITEM_ATTRIBUTE_" + std::string(magic_enum::enum_name(value)); - registerGlobalVariable(L, enumName, static_cast<lua_Number>(number)); + Lua::registerGlobalVariable(L, enumName, static_cast<lua_Number>(number)); } } @@ -840,7 +838,7 @@ void LuaEnums::initItemTypeEnums(lua_State* L) { } void LuaEnums::initFluidEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<Fluids_t>()) { + for (const auto value : magic_enum::enum_values<Fluids_t>()) { registerMagicEnum(L, value); } } @@ -912,7 +910,7 @@ void LuaEnums::initItemIdEnums(lua_State* L) { } void LuaEnums::initPlayerFlagEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<PlayerFlags_t>()) { + for (const auto value : magic_enum::enum_values<PlayerFlags_t>()) { registerMagicEnum(L, value); } } @@ -1202,7 +1200,7 @@ void LuaEnums::initReturnValueEnums(lua_State* L) { // Reload void LuaEnums::initReloadTypeEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<Reload_t>()) { + for (const auto value : magic_enum::enum_values<Reload_t>()) { registerMagicEnum(L, value); } } @@ -1226,7 +1224,7 @@ void LuaEnums::initCreaturesEventEnums(lua_State* L) { } void LuaEnums::initForgeEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<ForgeClassifications_t>()) { + for (const auto value : magic_enum::enum_values<ForgeClassifications_t>()) { registerMagicEnum(L, value); } } @@ -1240,7 +1238,7 @@ void LuaEnums::initWebhookEnums(lua_State* L) { } void LuaEnums::initBosstiaryEnums(lua_State* L) { - for (auto value : magic_enum::enum_values<BosstiaryRarity_t>()) { + for (const auto value : magic_enum::enum_values<BosstiaryRarity_t>()) { registerMagicEnum(L, value); } } @@ -1772,31 +1770,31 @@ void LuaEnums::effectsSoundEnums(lua_State* L) { void LuaEnums::initWheelEnums(lua_State* L) { std::string wheelNamespace = "WHEEL_INSTANT_"; - for (auto value : magic_enum::enum_values<WheelInstant_t>()) { + for (const auto value : magic_enum::enum_values<WheelInstant_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } wheelNamespace = "WHEEL_STAGE_"; - for (auto value : magic_enum::enum_values<WheelStage_t>()) { + for (const auto value : magic_enum::enum_values<WheelStage_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } wheelNamespace = "WHEEL_GRADE_"; - for (auto value : magic_enum::enum_values<WheelSpellGrade_t>()) { + for (const auto value : magic_enum::enum_values<WheelSpellGrade_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } wheelNamespace = "WHEEL_AVATAR_SKILL_"; - for (auto value : magic_enum::enum_values<WheelAvatarSkill_t>()) { + for (const auto value : magic_enum::enum_values<WheelAvatarSkill_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } wheelNamespace = "WHEEL_STAT_"; - for (auto value : magic_enum::enum_values<WheelStat_t>()) { + for (const auto value : magic_enum::enum_values<WheelStat_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } wheelNamespace = "WHEEL_BOOST_"; - for (auto value : magic_enum::enum_values<WheelSpellBoost_t>()) { + for (const auto value : magic_enum::enum_values<WheelSpellBoost_t>()) { registerMagicEnumNamespace(L, wheelNamespace, value); } } diff --git a/src/lua/functions/core/game/lua_enums.hpp b/src/lua/functions/core/game/lua_enums.hpp index d14ca0ceb54..465cc96afc3 100644 --- a/src/lua/functions/core/game/lua_enums.hpp +++ b/src/lua/functions/core/game/lua_enums.hpp @@ -9,11 +9,7 @@ #pragma once -#include "account/account.hpp" -#include "declarations.hpp" -#include "lua/scripts/luascript.hpp" - -class LuaEnums final : LuaScriptInterface { +class LuaEnums { public: static void init(lua_State* L); diff --git a/src/lua/functions/core/game/modal_window_functions.cpp b/src/lua/functions/core/game/modal_window_functions.cpp index a4851cfc85a..9d288716137 100644 --- a/src/lua/functions/core/game/modal_window_functions.cpp +++ b/src/lua/functions/core/game/modal_window_functions.cpp @@ -7,25 +7,56 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/players/player.hpp" #include "lua/functions/core/game/modal_window_functions.hpp" + +#include "creatures/players/player.hpp" #include "game/modal_window/modal_window.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ModalWindowFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "ModalWindow", "", ModalWindowFunctions::luaModalWindowCreate); + Lua::registerMetaMethod(L, "ModalWindow", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "ModalWindow", "getId", ModalWindowFunctions::luaModalWindowGetId); + Lua::registerMethod(L, "ModalWindow", "getTitle", ModalWindowFunctions::luaModalWindowGetTitle); + Lua::registerMethod(L, "ModalWindow", "getMessage", ModalWindowFunctions::luaModalWindowGetMessage); + + Lua::registerMethod(L, "ModalWindow", "setTitle", ModalWindowFunctions::luaModalWindowSetTitle); + Lua::registerMethod(L, "ModalWindow", "setMessage", ModalWindowFunctions::luaModalWindowSetMessage); + + Lua::registerMethod(L, "ModalWindow", "getButtonCount", ModalWindowFunctions::luaModalWindowGetButtonCount); + Lua::registerMethod(L, "ModalWindow", "getChoiceCount", ModalWindowFunctions::luaModalWindowGetChoiceCount); + + Lua::registerMethod(L, "ModalWindow", "addButton", ModalWindowFunctions::luaModalWindowAddButton); + Lua::registerMethod(L, "ModalWindow", "addChoice", ModalWindowFunctions::luaModalWindowAddChoice); + + Lua::registerMethod(L, "ModalWindow", "getDefaultEnterButton", ModalWindowFunctions::luaModalWindowGetDefaultEnterButton); + Lua::registerMethod(L, "ModalWindow", "setDefaultEnterButton", ModalWindowFunctions::luaModalWindowSetDefaultEnterButton); + + Lua::registerMethod(L, "ModalWindow", "getDefaultEscapeButton", ModalWindowFunctions::luaModalWindowGetDefaultEscapeButton); + Lua::registerMethod(L, "ModalWindow", "setDefaultEscapeButton", ModalWindowFunctions::luaModalWindowSetDefaultEscapeButton); + + Lua::registerMethod(L, "ModalWindow", "hasPriority", ModalWindowFunctions::luaModalWindowHasPriority); + Lua::registerMethod(L, "ModalWindow", "setPriority", ModalWindowFunctions::luaModalWindowSetPriority); + + Lua::registerMethod(L, "ModalWindow", "sendToPlayer", ModalWindowFunctions::luaModalWindowSendToPlayer); +} // ModalWindow int ModalWindowFunctions::luaModalWindowCreate(lua_State* L) { // ModalWindow(id, title, message) - const std::string &message = getString(L, 4); - const std::string &title = getString(L, 3); - uint32_t id = getNumber<uint32_t>(L, 2); + const std::string &message = Lua::getString(L, 4); + const std::string &title = Lua::getString(L, 3); + uint32_t id = Lua::getNumber<uint32_t>(L, 2); - pushUserdata<ModalWindow>(L, std::make_shared<ModalWindow>(id, title, message)); - setMetatable(L, -1, "ModalWindow"); + Lua::pushUserdata<ModalWindow>(L, std::make_shared<ModalWindow>(id, title, message)); + Lua::setMetatable(L, -1, "ModalWindow"); return 1; } int ModalWindowFunctions::luaModalWindowGetId(lua_State* L) { // modalWindow:getId() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { lua_pushnumber(L, window->id); } else { @@ -36,9 +67,9 @@ int ModalWindowFunctions::luaModalWindowGetId(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetTitle(lua_State* L) { // modalWindow:getTitle() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - pushString(L, window->title); + Lua::pushString(L, window->title); } else { lua_pushnil(L); } @@ -47,9 +78,9 @@ int ModalWindowFunctions::luaModalWindowGetTitle(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetMessage(lua_State* L) { // modalWindow:getMessage() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - pushString(L, window->message); + Lua::pushString(L, window->message); } else { lua_pushnil(L); } @@ -58,11 +89,11 @@ int ModalWindowFunctions::luaModalWindowGetMessage(lua_State* L) { int ModalWindowFunctions::luaModalWindowSetTitle(lua_State* L) { // modalWindow:setTitle(text) - const std::string &text = getString(L, 2); - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const std::string &text = Lua::getString(L, 2); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { window->title = text; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -71,11 +102,11 @@ int ModalWindowFunctions::luaModalWindowSetTitle(lua_State* L) { int ModalWindowFunctions::luaModalWindowSetMessage(lua_State* L) { // modalWindow:setMessage(text) - const std::string &text = getString(L, 2); - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const std::string &text = Lua::getString(L, 2); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { window->message = text; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -84,7 +115,7 @@ int ModalWindowFunctions::luaModalWindowSetMessage(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetButtonCount(lua_State* L) { // modalWindow:getButtonCount() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { lua_pushnumber(L, window->buttons.size()); } else { @@ -95,7 +126,7 @@ int ModalWindowFunctions::luaModalWindowGetButtonCount(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetChoiceCount(lua_State* L) { // modalWindow:getChoiceCount() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { lua_pushnumber(L, window->choices.size()); } else { @@ -106,12 +137,12 @@ int ModalWindowFunctions::luaModalWindowGetChoiceCount(lua_State* L) { int ModalWindowFunctions::luaModalWindowAddButton(lua_State* L) { // modalWindow:addButton(id, text) - const std::string &text = getString(L, 3); - uint8_t id = getNumber<uint8_t>(L, 2); - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const std::string &text = Lua::getString(L, 3); + uint8_t id = Lua::getNumber<uint8_t>(L, 2); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { window->buttons.emplace_back(text, id); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -120,12 +151,12 @@ int ModalWindowFunctions::luaModalWindowAddButton(lua_State* L) { int ModalWindowFunctions::luaModalWindowAddChoice(lua_State* L) { // modalWindow:addChoice(id, text) - const std::string &text = getString(L, 3); - uint8_t id = getNumber<uint8_t>(L, 2); - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const std::string &text = Lua::getString(L, 3); + uint8_t id = Lua::getNumber<uint8_t>(L, 2); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { window->choices.emplace_back(text, id); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -134,7 +165,7 @@ int ModalWindowFunctions::luaModalWindowAddChoice(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetDefaultEnterButton(lua_State* L) { // modalWindow:getDefaultEnterButton() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { lua_pushnumber(L, window->defaultEnterButton); } else { @@ -145,10 +176,10 @@ int ModalWindowFunctions::luaModalWindowGetDefaultEnterButton(lua_State* L) { int ModalWindowFunctions::luaModalWindowSetDefaultEnterButton(lua_State* L) { // modalWindow:setDefaultEnterButton(buttonId) - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - window->defaultEnterButton = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + window->defaultEnterButton = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -157,7 +188,7 @@ int ModalWindowFunctions::luaModalWindowSetDefaultEnterButton(lua_State* L) { int ModalWindowFunctions::luaModalWindowGetDefaultEscapeButton(lua_State* L) { // modalWindow:getDefaultEscapeButton() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { lua_pushnumber(L, window->defaultEscapeButton); } else { @@ -168,10 +199,10 @@ int ModalWindowFunctions::luaModalWindowGetDefaultEscapeButton(lua_State* L) { int ModalWindowFunctions::luaModalWindowSetDefaultEscapeButton(lua_State* L) { // modalWindow:setDefaultEscapeButton(buttonId) - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - window->defaultEscapeButton = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + window->defaultEscapeButton = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -180,9 +211,9 @@ int ModalWindowFunctions::luaModalWindowSetDefaultEscapeButton(lua_State* L) { int ModalWindowFunctions::luaModalWindowHasPriority(lua_State* L) { // modalWindow:hasPriority() - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - pushBoolean(L, window->priority); + Lua::pushBoolean(L, window->priority); } else { lua_pushnil(L); } @@ -191,10 +222,10 @@ int ModalWindowFunctions::luaModalWindowHasPriority(lua_State* L) { int ModalWindowFunctions::luaModalWindowSetPriority(lua_State* L) { // modalWindow:setPriority(priority) - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { - window->priority = getBoolean(L, 2); - pushBoolean(L, true); + window->priority = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -203,18 +234,18 @@ int ModalWindowFunctions::luaModalWindowSetPriority(lua_State* L) { int ModalWindowFunctions::luaModalWindowSendToPlayer(lua_State* L) { // modalWindow:sendToPlayer(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - const auto &window = getUserdataShared<ModalWindow>(L, 1); + const auto &window = Lua::getUserdataShared<ModalWindow>(L, 1); if (window) { if (!player->hasModalWindowOpen(window->id)) { player->sendModalWindow(*window); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/core/game/modal_window_functions.hpp b/src/lua/functions/core/game/modal_window_functions.hpp index 9d6b9192026..83867888d89 100644 --- a/src/lua/functions/core/game/modal_window_functions.hpp +++ b/src/lua/functions/core/game/modal_window_functions.hpp @@ -9,38 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ModalWindowFunctions final : LuaScriptInterface { +class ModalWindowFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "ModalWindow", "", ModalWindowFunctions::luaModalWindowCreate); - registerMetaMethod(L, "ModalWindow", "__eq", ModalWindowFunctions::luaUserdataCompare); - - registerMethod(L, "ModalWindow", "getId", ModalWindowFunctions::luaModalWindowGetId); - registerMethod(L, "ModalWindow", "getTitle", ModalWindowFunctions::luaModalWindowGetTitle); - registerMethod(L, "ModalWindow", "getMessage", ModalWindowFunctions::luaModalWindowGetMessage); - - registerMethod(L, "ModalWindow", "setTitle", ModalWindowFunctions::luaModalWindowSetTitle); - registerMethod(L, "ModalWindow", "setMessage", ModalWindowFunctions::luaModalWindowSetMessage); - - registerMethod(L, "ModalWindow", "getButtonCount", ModalWindowFunctions::luaModalWindowGetButtonCount); - registerMethod(L, "ModalWindow", "getChoiceCount", ModalWindowFunctions::luaModalWindowGetChoiceCount); - - registerMethod(L, "ModalWindow", "addButton", ModalWindowFunctions::luaModalWindowAddButton); - registerMethod(L, "ModalWindow", "addChoice", ModalWindowFunctions::luaModalWindowAddChoice); - - registerMethod(L, "ModalWindow", "getDefaultEnterButton", ModalWindowFunctions::luaModalWindowGetDefaultEnterButton); - registerMethod(L, "ModalWindow", "setDefaultEnterButton", ModalWindowFunctions::luaModalWindowSetDefaultEnterButton); - - registerMethod(L, "ModalWindow", "getDefaultEscapeButton", ModalWindowFunctions::luaModalWindowGetDefaultEscapeButton); - registerMethod(L, "ModalWindow", "setDefaultEscapeButton", ModalWindowFunctions::luaModalWindowSetDefaultEscapeButton); - - registerMethod(L, "ModalWindow", "hasPriority", ModalWindowFunctions::luaModalWindowHasPriority); - registerMethod(L, "ModalWindow", "setPriority", ModalWindowFunctions::luaModalWindowSetPriority); - - registerMethod(L, "ModalWindow", "sendToPlayer", ModalWindowFunctions::luaModalWindowSendToPlayer); - } + static void init(lua_State* L); private: static int luaModalWindowCreate(lua_State* L); diff --git a/src/lua/functions/core/game/zone_functions.cpp b/src/lua/functions/core/game/zone_functions.cpp index d973f1b003c..43fe586997a 100644 --- a/src/lua/functions/core/game/zone_functions.cpp +++ b/src/lua/functions/core/game/zone_functions.cpp @@ -8,122 +8,153 @@ */ #include "lua/functions/core/game/zone_functions.hpp" + #include "game/zones/zone.hpp" #include "game/game.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ZoneFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Zone", "", ZoneFunctions::luaZoneCreate); + Lua::registerMetaMethod(L, "Zone", "__eq", ZoneFunctions::luaZoneCompare); + + Lua::registerMethod(L, "Zone", "getName", ZoneFunctions::luaZoneGetName); + Lua::registerMethod(L, "Zone", "addArea", ZoneFunctions::luaZoneAddArea); + Lua::registerMethod(L, "Zone", "subtractArea", ZoneFunctions::luaZoneSubtractArea); + Lua::registerMethod(L, "Zone", "getRemoveDestination", ZoneFunctions::luaZoneGetRemoveDestination); + Lua::registerMethod(L, "Zone", "setRemoveDestination", ZoneFunctions::luaZoneSetRemoveDestination); + Lua::registerMethod(L, "Zone", "getPositions", ZoneFunctions::luaZoneGetPositions); + Lua::registerMethod(L, "Zone", "getCreatures", ZoneFunctions::luaZoneGetCreatures); + Lua::registerMethod(L, "Zone", "getPlayers", ZoneFunctions::luaZoneGetPlayers); + Lua::registerMethod(L, "Zone", "getMonsters", ZoneFunctions::luaZoneGetMonsters); + Lua::registerMethod(L, "Zone", "getNpcs", ZoneFunctions::luaZoneGetNpcs); + Lua::registerMethod(L, "Zone", "getItems", ZoneFunctions::luaZoneGetItems); + + Lua::registerMethod(L, "Zone", "removePlayers", ZoneFunctions::luaZoneRemovePlayers); + Lua::registerMethod(L, "Zone", "removeMonsters", ZoneFunctions::luaZoneRemoveMonsters); + Lua::registerMethod(L, "Zone", "removeNpcs", ZoneFunctions::luaZoneRemoveNpcs); + Lua::registerMethod(L, "Zone", "refresh", ZoneFunctions::luaZoneRefresh); + + Lua::registerMethod(L, "Zone", "setMonsterVariant", ZoneFunctions::luaZoneSetMonsterVariant); + + // static methods + Lua::registerMethod(L, "Zone", "getByPosition", ZoneFunctions::luaZoneGetByPosition); + Lua::registerMethod(L, "Zone", "getByName", ZoneFunctions::luaZoneGetByName); + Lua::registerMethod(L, "Zone", "getAll", ZoneFunctions::luaZoneGetAll); +} // Zone int ZoneFunctions::luaZoneCreate(lua_State* L) { // Zone(name) - auto name = getString(L, 2); + const auto name = Lua::getString(L, 2); auto zone = Zone::getZone(name); if (!zone) { zone = Zone::addZone(name); } - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); return 1; } int ZoneFunctions::luaZoneCompare(lua_State* L) { - auto zone1 = getUserdataShared<Zone>(L, 1); - auto zone2 = getUserdataShared<Zone>(L, 2); + const auto &zone1 = Lua::getUserdataShared<Zone>(L, 1); + const auto &zone2 = Lua::getUserdataShared<Zone>(L, 2); if (!zone1) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (!zone2) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, zone1->getName() == zone2->getName()); + Lua::pushBoolean(L, zone1->getName() == zone2->getName()); return 1; } int ZoneFunctions::luaZoneGetName(lua_State* L) { // Zone:getName() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushString(L, zone->getName()); + Lua::pushString(L, zone->getName()); return 1; } int ZoneFunctions::luaZoneAddArea(lua_State* L) { // Zone:addArea(fromPos, toPos) - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto fromPos = getPosition(L, 2); - auto toPos = getPosition(L, 3); - auto area = Area(fromPos, toPos); + const auto fromPos = Lua::getPosition(L, 2); + const auto toPos = Lua::getPosition(L, 3); + const auto area = Area(fromPos, toPos); zone->addArea(area); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ZoneFunctions::luaZoneSubtractArea(lua_State* L) { // Zone:subtractArea(fromPos, toPos) - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto fromPos = getPosition(L, 2); - auto toPos = getPosition(L, 3); - auto area = Area(fromPos, toPos); + const auto fromPos = Lua::getPosition(L, 2); + const auto toPos = Lua::getPosition(L, 3); + const auto area = Area(fromPos, toPos); zone->subtractArea(area); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ZoneFunctions::luaZoneGetRemoveDestination(lua_State* L) { // Zone:getRemoveDestination() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); return 1; } - pushPosition(L, zone->getRemoveDestination()); + Lua::pushPosition(L, zone->getRemoveDestination()); return 1; } int ZoneFunctions::luaZoneSetRemoveDestination(lua_State* L) { // Zone:setRemoveDestination(pos) - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); return 1; } - auto pos = getPosition(L, 2); + const auto pos = Lua::getPosition(L, 2); zone->setRemoveDestination(pos); return 1; } int ZoneFunctions::luaZoneGetPositions(lua_State* L) { // Zone:getPositions() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto positions = zone->getPositions(); + const auto positions = zone->getPositions(); lua_createtable(L, static_cast<int>(positions.size()), 0); int index = 0; for (auto pos : positions) { index++; - pushPosition(L, pos); + Lua::pushPosition(L, pos); lua_rawseti(L, -2, index); } return 1; @@ -131,20 +162,20 @@ int ZoneFunctions::luaZoneGetPositions(lua_State* L) { int ZoneFunctions::luaZoneGetCreatures(lua_State* L) { // Zone:getCreatures() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto creatures = zone->getCreatures(); + const auto &creatures = zone->getCreatures(); lua_createtable(L, static_cast<int>(creatures.size()), 0); int index = 0; - for (auto creature : creatures) { + for (const auto &creature : creatures) { index++; - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, index); } return 1; @@ -152,20 +183,20 @@ int ZoneFunctions::luaZoneGetCreatures(lua_State* L) { int ZoneFunctions::luaZoneGetPlayers(lua_State* L) { // Zone:getPlayers() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto players = zone->getPlayers(); + const auto &players = zone->getPlayers(); lua_createtable(L, static_cast<int>(players.size()), 0); int index = 0; - for (auto player : players) { + for (const auto &player : players) { index++; - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); lua_rawseti(L, -2, index); } return 1; @@ -173,20 +204,20 @@ int ZoneFunctions::luaZoneGetPlayers(lua_State* L) { int ZoneFunctions::luaZoneGetMonsters(lua_State* L) { // Zone:getMonsters() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto monsters = zone->getMonsters(); + const auto &monsters = zone->getMonsters(); lua_createtable(L, static_cast<int>(monsters.size()), 0); int index = 0; - for (auto monster : monsters) { + for (const auto &monster : monsters) { index++; - pushUserdata<Monster>(L, monster); - setMetatable(L, -1, "Monster"); + Lua::pushUserdata<Monster>(L, monster); + Lua::setMetatable(L, -1, "Monster"); lua_rawseti(L, -2, index); } return 1; @@ -194,20 +225,20 @@ int ZoneFunctions::luaZoneGetMonsters(lua_State* L) { int ZoneFunctions::luaZoneGetNpcs(lua_State* L) { // Zone:getNpcs() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto npcs = zone->getNpcs(); + const auto &npcs = zone->getNpcs(); lua_createtable(L, static_cast<int>(npcs.size()), 0); int index = 0; - for (auto npc : npcs) { + for (const auto &npc : npcs) { index++; - pushUserdata<Npc>(L, npc); - setMetatable(L, -1, "Npc"); + Lua::pushUserdata<Npc>(L, npc); + Lua::setMetatable(L, -1, "Npc"); lua_rawseti(L, -2, index); } return 1; @@ -215,20 +246,20 @@ int ZoneFunctions::luaZoneGetNpcs(lua_State* L) { int ZoneFunctions::luaZoneGetItems(lua_State* L) { // Zone:getItems() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto items = zone->getItems(); + const auto &items = zone->getItems(); lua_createtable(L, static_cast<int>(items.size()), 0); int index = 0; - for (auto item : items) { + for (const auto &item : items) { index++; - pushUserdata<Item>(L, item); - setMetatable(L, -1, "Item"); + Lua::pushUserdata<Item>(L, item); + Lua::setMetatable(L, -1, "Item"); lua_rawseti(L, -2, index); } return 1; @@ -236,10 +267,10 @@ int ZoneFunctions::luaZoneGetItems(lua_State* L) { int ZoneFunctions::luaZoneRemovePlayers(lua_State* L) { // Zone:removePlayers() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -249,10 +280,10 @@ int ZoneFunctions::luaZoneRemovePlayers(lua_State* L) { int ZoneFunctions::luaZoneRemoveMonsters(lua_State* L) { // Zone:removeMonsters() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } zone->removeMonsters(); @@ -261,10 +292,10 @@ int ZoneFunctions::luaZoneRemoveMonsters(lua_State* L) { int ZoneFunctions::luaZoneRemoveNpcs(lua_State* L) { // Zone:removeNpcs() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } zone->removeNpcs(); @@ -273,50 +304,50 @@ int ZoneFunctions::luaZoneRemoveNpcs(lua_State* L) { int ZoneFunctions::luaZoneSetMonsterVariant(lua_State* L) { // Zone:setMonsterVariant(variant) - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto variant = getString(L, 2); + const auto variant = Lua::getString(L, 2); if (variant.empty()) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } zone->setMonsterVariant(variant); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ZoneFunctions::luaZoneGetByName(lua_State* L) { // Zone.getByName(name) - auto name = getString(L, 1); - auto zone = Zone::getZone(name); + const auto name = Lua::getString(L, 1); + const auto &zone = Zone::getZone(name); if (!zone) { lua_pushnil(L); return 1; } - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); return 1; } int ZoneFunctions::luaZoneGetByPosition(lua_State* L) { // Zone.getByPosition(pos) - auto pos = getPosition(L, 1); - auto tile = g_game().map.getTile(pos); + const auto pos = Lua::getPosition(L, 1); + const auto &tile = g_game().map.getTile(pos); if (!tile) { lua_pushnil(L); return 1; } int index = 0; - auto zones = tile->getZones(); + const auto &zones = tile->getZones(); lua_createtable(L, static_cast<int>(zones.size()), 0); - for (auto zone : zones) { + for (const auto &zone : zones) { index++; - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); lua_rawseti(L, -2, index); } return 1; @@ -324,13 +355,13 @@ int ZoneFunctions::luaZoneGetByPosition(lua_State* L) { int ZoneFunctions::luaZoneGetAll(lua_State* L) { // Zone.getAll() - auto zones = Zone::getZones(); + const auto &zones = Zone::getZones(); lua_createtable(L, static_cast<int>(zones.size()), 0); int index = 0; - for (auto zone : zones) { + for (const auto &zone : zones) { index++; - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); lua_rawseti(L, -2, index); } return 1; @@ -338,9 +369,9 @@ int ZoneFunctions::luaZoneGetAll(lua_State* L) { int ZoneFunctions::luaZoneRefresh(lua_State* L) { // Zone:refresh() - auto zone = getUserdataShared<Zone>(L, 1); + const auto &zone = Lua::getUserdataShared<Zone>(L, 1); if (!zone) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ZONE_NOT_FOUND)); return 1; } zone->refresh(); diff --git a/src/lua/functions/core/game/zone_functions.hpp b/src/lua/functions/core/game/zone_functions.hpp index 2a3bbd0f8ea..cf1fa7cd73e 100644 --- a/src/lua/functions/core/game/zone_functions.hpp +++ b/src/lua/functions/core/game/zone_functions.hpp @@ -1,39 +1,10 @@ #pragma once -#include "lua/scripts/luascript.hpp" - class Zone; -class ZoneFunctions final : LuaScriptInterface { +class ZoneFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Zone", "", ZoneFunctions::luaZoneCreate); - registerMetaMethod(L, "Zone", "__eq", ZoneFunctions::luaZoneCompare); - - registerMethod(L, "Zone", "getName", ZoneFunctions::luaZoneGetName); - registerMethod(L, "Zone", "addArea", ZoneFunctions::luaZoneAddArea); - registerMethod(L, "Zone", "subtractArea", ZoneFunctions::luaZoneSubtractArea); - registerMethod(L, "Zone", "getRemoveDestination", ZoneFunctions::luaZoneGetRemoveDestination); - registerMethod(L, "Zone", "setRemoveDestination", ZoneFunctions::luaZoneSetRemoveDestination); - registerMethod(L, "Zone", "getPositions", ZoneFunctions::luaZoneGetPositions); - registerMethod(L, "Zone", "getCreatures", ZoneFunctions::luaZoneGetCreatures); - registerMethod(L, "Zone", "getPlayers", ZoneFunctions::luaZoneGetPlayers); - registerMethod(L, "Zone", "getMonsters", ZoneFunctions::luaZoneGetMonsters); - registerMethod(L, "Zone", "getNpcs", ZoneFunctions::luaZoneGetNpcs); - registerMethod(L, "Zone", "getItems", ZoneFunctions::luaZoneGetItems); - - registerMethod(L, "Zone", "removePlayers", ZoneFunctions::luaZoneRemovePlayers); - registerMethod(L, "Zone", "removeMonsters", ZoneFunctions::luaZoneRemoveMonsters); - registerMethod(L, "Zone", "removeNpcs", ZoneFunctions::luaZoneRemoveNpcs); - registerMethod(L, "Zone", "refresh", ZoneFunctions::luaZoneRefresh); - - registerMethod(L, "Zone", "setMonsterVariant", ZoneFunctions::luaZoneSetMonsterVariant); - - // static methods - registerMethod(L, "Zone", "getByPosition", ZoneFunctions::luaZoneGetByPosition); - registerMethod(L, "Zone", "getByName", ZoneFunctions::luaZoneGetByName); - registerMethod(L, "Zone", "getAll", ZoneFunctions::luaZoneGetAll); - } + static void init(lua_State* L); private: static int luaZoneCreate(lua_State* L); diff --git a/src/lua/functions/core/libs/bit_functions.cpp b/src/lua/functions/core/libs/bit_functions.cpp deleted file mode 100644 index 94e5f709b5d..00000000000 --- a/src/lua/functions/core/libs/bit_functions.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Canary - A free and open-source MMORPG server emulator - * Copyright (©) 2019-2024 OpenTibiaBR <opentibiabr@outlook.com> - * Repository: https://github.com/opentibiabr/canary - * License: https://github.com/opentibiabr/canary/blob/main/LICENSE - * Contributors: https://github.com/opentibiabr/canary/graphs/contributors - * Website: https://docs.opentibiabr.com/ - */ - -#include "lua/functions/core/libs/bit_functions.hpp" - -#ifndef LUAJIT_VERSION -int GlobalFunctions::luaBitNot(lua_State* L) { - int32_t number = getNumber<int32_t>(L, -1); - lua_pushnumber(L, ~number); - return 1; -} - - #define MULTIOP(name, op) \ - int GlobalFunctions::luaBit##name(lua_State* L) \ { \ - int n = lua_gettop(L); \ - uint32_t w = getNumber<uint32_t>(L, -1); \ - for (int i = 1; i < n; ++i) \ - w op getNumber<uint32_t>(L, i); \ - lua_pushnumber(L, w); \ - return 1; \ - } - -MULTIOP(And, &=) -MULTIOP(Or, |=) -MULTIOP(Xor, ^=) - - #define SHIFTOP(name, op) \ - int GlobalFunctions::luaBit##name(lua_State* L) \ { \ - uint32_t n1 = getNumber<uint32_t>(L, 1), n2 = getNumber<uint32_t>(L, 2); \ - lua_pushnumber(L, (n1 op n2)); \ - return 1; \ - } - -SHIFTOP(LeftShift, <<) -SHIFTOP(RightShift, >>) -#endif diff --git a/src/lua/functions/core/libs/bit_functions.hpp b/src/lua/functions/core/libs/bit_functions.hpp deleted file mode 100644 index c2143fde198..00000000000 --- a/src/lua/functions/core/libs/bit_functions.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Canary - A free and open-source MMORPG server emulator - * Copyright (©) 2019-2024 OpenTibiaBR <opentibiabr@outlook.com> - * Repository: https://github.com/opentibiabr/canary - * License: https://github.com/opentibiabr/canary/blob/main/LICENSE - * Contributors: https://github.com/opentibiabr/canary/graphs/contributors - * Website: https://docs.opentibiabr.com/ - */ - -#pragma once - -#include "lua/scripts/luascript.hpp" - -class BitFunctions final : LuaScriptInterface { -public: - static void init(lua_State* L) { -#ifndef LUAJIT_VERSION - registerTable(L, "bit"); - registerMethod(L, "bit", "bnot", BitFunctions::luaBitNot); - registerMethod(L, "bit", "band", BitFunctions::luaBitAnd); - registerMethod(L, "bit", "bor", BitFunctions::luaBitOr); - registerMethod(L, "bit", "bxor", BitFunctions::luaBitXor); - registerMethod(L, "bit", "lshift", BitFunctions::luaBitLeftShift); - registerMethod(L, "bit", "rshift", BitFunctions::luaBitRightShift); -#endif - } - -private: -#ifndef LUAJIT_VERSION - static int luaBitAnd(lua_State* L); - static int luaBitLeftShift(lua_State* L); - static int luaBitNot(lua_State* L); - static int luaBitOr(lua_State* L); - static int luaBitRightShift(lua_State* L); - static int luaBitXor(lua_State* L); -#endif -}; diff --git a/src/lua/functions/core/libs/core_libs_functions.hpp b/src/lua/functions/core/libs/core_libs_functions.hpp index 614c59e6e3d..658b560c2f4 100644 --- a/src/lua/functions/core/libs/core_libs_functions.hpp +++ b/src/lua/functions/core/libs/core_libs_functions.hpp @@ -10,7 +10,6 @@ #pragma once #include "lua/scripts/luascript.hpp" -#include "lua/functions/core/libs/bit_functions.hpp" #include "lua/functions/core/libs/db_functions.hpp" #include "lua/functions/core/libs/result_functions.hpp" #include "lua/functions/core/libs/logger_functions.hpp" @@ -19,8 +18,13 @@ class CoreLibsFunctions final : LuaScriptInterface { public: + explicit CoreLibsFunctions(lua_State* L) : + LuaScriptInterface("CoreLibsFunctions") { + init(L); + } + ~CoreLibsFunctions() override = default; + static void init(lua_State* L) { - BitFunctions::init(L); DBFunctions::init(L); ResultFunctions::init(L); LoggerFunctions::init(L); diff --git a/src/lua/functions/core/libs/db_functions.cpp b/src/lua/functions/core/libs/db_functions.cpp index bdfbac8f501..6b56c5cd148 100644 --- a/src/lua/functions/core/libs/db_functions.cpp +++ b/src/lua/functions/core/libs/db_functions.cpp @@ -7,13 +7,27 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/core/libs/db_functions.hpp" + #include "database/databasemanager.hpp" #include "database/databasetasks.hpp" -#include "lua/functions/core/libs/db_functions.hpp" #include "lua/scripts/lua_environment.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void DBFunctions::init(lua_State* L) { + Lua::registerTable(L, "db"); + Lua::registerMethod(L, "db", "query", DBFunctions::luaDatabaseExecute); + Lua::registerMethod(L, "db", "asyncQuery", DBFunctions::luaDatabaseAsyncExecute); + Lua::registerMethod(L, "db", "storeQuery", DBFunctions::luaDatabaseStoreQuery); + Lua::registerMethod(L, "db", "asyncStoreQuery", DBFunctions::luaDatabaseAsyncStoreQuery); + Lua::registerMethod(L, "db", "escapeString", DBFunctions::luaDatabaseEscapeString); + Lua::registerMethod(L, "db", "escapeBlob", DBFunctions::luaDatabaseEscapeBlob); + Lua::registerMethod(L, "db", "lastInsertId", DBFunctions::luaDatabaseLastInsertId); + Lua::registerMethod(L, "db", "tableExists", DBFunctions::luaDatabaseTableExists); +} int DBFunctions::luaDatabaseExecute(lua_State* L) { - pushBoolean(L, Database::getInstance().executeQuery(getString(L, -1))); + Lua::pushBoolean(L, Database::getInstance().executeQuery(Lua::getString(L, -1))); return 1; } @@ -21,36 +35,36 @@ int DBFunctions::luaDatabaseAsyncExecute(lua_State* L) { std::function<void(DBResult_ptr, bool)> callback; if (lua_gettop(L) > 1) { int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); - auto scriptId = getScriptEnv()->getScriptId(); - callback = [ref, scriptId](DBResult_ptr, bool success) { + auto scriptId = Lua::getScriptEnv()->getScriptId(); + callback = [ref, scriptId](const DBResult_ptr &, bool success) { lua_State* luaState = g_luaEnvironment().getLuaState(); if (!luaState) { return; } - if (!DBFunctions::reserveScriptEnv()) { + if (!Lua::reserveScriptEnv()) { luaL_unref(luaState, LUA_REGISTRYINDEX, ref); return; } lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref); - pushBoolean(luaState, success); - auto env = getScriptEnv(); + Lua::pushBoolean(luaState, success); + const auto env = Lua::getScriptEnv(); env->setScriptId(scriptId, &g_luaEnvironment()); g_luaEnvironment().callFunction(1); luaL_unref(luaState, LUA_REGISTRYINDEX, ref); }; } - g_databaseTasks().execute(getString(L, -1), callback); + g_databaseTasks().execute(Lua::getString(L, -1), callback); return 0; } int DBFunctions::luaDatabaseStoreQuery(lua_State* L) { - if (DBResult_ptr res = Database::getInstance().storeQuery(getString(L, -1))) { + if (const DBResult_ptr &res = Database::getInstance().storeQuery(Lua::getString(L, -1))) { lua_pushnumber(L, ScriptEnvironment::addResult(res)); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } @@ -59,14 +73,14 @@ int DBFunctions::luaDatabaseAsyncStoreQuery(lua_State* L) { std::function<void(DBResult_ptr, bool)> callback; if (lua_gettop(L) > 1) { int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); - auto scriptId = getScriptEnv()->getScriptId(); - callback = [ref, scriptId](DBResult_ptr result, bool) { + auto scriptId = Lua::getScriptEnv()->getScriptId(); + callback = [ref, scriptId](const DBResult_ptr &result, bool) { lua_State* luaState = g_luaEnvironment().getLuaState(); if (!luaState) { return; } - if (!DBFunctions::reserveScriptEnv()) { + if (!Lua::reserveScriptEnv()) { luaL_unref(luaState, LUA_REGISTRYINDEX, ref); return; } @@ -75,27 +89,27 @@ int DBFunctions::luaDatabaseAsyncStoreQuery(lua_State* L) { if (result) { lua_pushnumber(luaState, ScriptEnvironment::addResult(result)); } else { - pushBoolean(luaState, false); + Lua::pushBoolean(luaState, false); } - auto env = getScriptEnv(); + const auto env = Lua::getScriptEnv(); env->setScriptId(scriptId, &g_luaEnvironment()); g_luaEnvironment().callFunction(1); luaL_unref(luaState, LUA_REGISTRYINDEX, ref); }; } - g_databaseTasks().store(getString(L, -1), callback); + g_databaseTasks().store(Lua::getString(L, -1), callback); return 0; } int DBFunctions::luaDatabaseEscapeString(lua_State* L) { - pushString(L, Database::getInstance().escapeString(getString(L, -1))); + Lua::pushString(L, Database::getInstance().escapeString(Lua::getString(L, -1))); return 1; } int DBFunctions::luaDatabaseEscapeBlob(lua_State* L) { - uint32_t length = getNumber<uint32_t>(L, 2); - pushString(L, Database::getInstance().escapeBlob(getString(L, 1).c_str(), length)); + const uint32_t length = Lua::getNumber<uint32_t>(L, 2); + Lua::pushString(L, Database::getInstance().escapeBlob(Lua::getString(L, 1).c_str(), length)); return 1; } @@ -105,6 +119,6 @@ int DBFunctions::luaDatabaseLastInsertId(lua_State* L) { } int DBFunctions::luaDatabaseTableExists(lua_State* L) { - pushBoolean(L, DatabaseManager::tableExists(getString(L, -1))); + Lua::pushBoolean(L, DatabaseManager::tableExists(Lua::getString(L, -1))); return 1; } diff --git a/src/lua/functions/core/libs/db_functions.hpp b/src/lua/functions/core/libs/db_functions.hpp index 99b69f1f7ba..50181411add 100644 --- a/src/lua/functions/core/libs/db_functions.hpp +++ b/src/lua/functions/core/libs/db_functions.hpp @@ -9,21 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class DBFunctions final : LuaScriptInterface { +class DBFunctions { public: - static void init(lua_State* L) { - registerTable(L, "db"); - registerMethod(L, "db", "query", DBFunctions::luaDatabaseExecute); - registerMethod(L, "db", "asyncQuery", DBFunctions::luaDatabaseAsyncExecute); - registerMethod(L, "db", "storeQuery", DBFunctions::luaDatabaseStoreQuery); - registerMethod(L, "db", "asyncStoreQuery", DBFunctions::luaDatabaseAsyncStoreQuery); - registerMethod(L, "db", "escapeString", DBFunctions::luaDatabaseEscapeString); - registerMethod(L, "db", "escapeBlob", DBFunctions::luaDatabaseEscapeBlob); - registerMethod(L, "db", "lastInsertId", DBFunctions::luaDatabaseLastInsertId); - registerMethod(L, "db", "tableExists", DBFunctions::luaDatabaseTableExists); - } + static void init(lua_State* L); private: static int luaDatabaseAsyncExecute(lua_State* L); diff --git a/src/lua/functions/core/libs/kv_functions.cpp b/src/lua/functions/core/libs/kv_functions.cpp index 7ef21f861f7..8061e2e9cd8 100644 --- a/src/lua/functions/core/libs/kv_functions.cpp +++ b/src/lua/functions/core/libs/kv_functions.cpp @@ -7,50 +7,68 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/core/libs/kv_functions.hpp" + #include <variant> #include "kv/kv.hpp" -#include "lua/functions/core/libs/kv_functions.hpp" #include "lua/scripts/lua_environment.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void KVFunctions::init(lua_State* L) { + Lua::registerTable(L, "kv"); + Lua::registerMethod(L, "kv", "scoped", KVFunctions::luaKVScoped); + Lua::registerMethod(L, "kv", "set", KVFunctions::luaKVSet); + Lua::registerMethod(L, "kv", "get", KVFunctions::luaKVGet); + Lua::registerMethod(L, "kv", "keys", KVFunctions::luaKVKeys); + Lua::registerMethod(L, "kv", "remove", KVFunctions::luaKVRemove); + + Lua::registerClass(L, "KV", ""); + Lua::registerMethod(L, "KV", "scoped", KVFunctions::luaKVScoped); + Lua::registerMethod(L, "KV", "set", KVFunctions::luaKVSet); + Lua::registerMethod(L, "KV", "get", KVFunctions::luaKVGet); + Lua::registerMethod(L, "KV", "keys", KVFunctions::luaKVKeys); + Lua::registerMethod(L, "KV", "remove", KVFunctions::luaKVRemove); +} int KVFunctions::luaKVScoped(lua_State* L) { // KV.scoped(key) | KV:scoped(key) - auto key = getString(L, -1); + const auto key = Lua::getString(L, -1); - if (isUserdata(L, 1)) { - auto scopedKV = getUserdataShared<KV>(L, 1); - auto newScope = scopedKV->scoped(key); - pushUserdata<KV>(L, newScope); - setMetatable(L, -1, "KV"); + if (Lua::isUserdata(L, 1)) { + const auto &scopedKV = Lua::getUserdataShared<KV>(L, 1); + const auto &newScope = scopedKV->scoped(key); + Lua::pushUserdata<KV>(L, newScope); + Lua::setMetatable(L, -1, "KV"); return 1; } - auto scopedKV = g_kv().scoped(key); - pushUserdata<KV>(L, scopedKV); - setMetatable(L, -1, "KV"); + const auto &scopedKV = g_kv().scoped(key); + Lua::pushUserdata<KV>(L, scopedKV); + Lua::setMetatable(L, -1, "KV"); return 1; } int KVFunctions::luaKVSet(lua_State* L) { // KV.set(key, value) | scopedKV:set(key, value) - auto key = getString(L, -2); - auto valueWrapper = getValueWrapper(L); + const auto key = Lua::getString(L, -2); + const auto &valueWrapper = getValueWrapper(L); if (!valueWrapper) { g_logger().warn("[{}] invalid param type", __FUNCTION__); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - if (isUserdata(L, 1)) { - auto scopedKV = getUserdataShared<KV>(L, 1); + if (Lua::isUserdata(L, 1)) { + const auto &scopedKV = Lua::getUserdataShared<KV>(L, 1); scopedKV->set(key, valueWrapper.value()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } g_kv().set(key, valueWrapper.value()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -58,13 +76,13 @@ int KVFunctions::luaKVGet(lua_State* L) { // KV.get(key[, forceLoad = false]) | scopedKV:get(key[, forceLoad = false]) std::optional<ValueWrapper> valueWrapper; bool forceLoad = false; - auto key = getString(L, -1); - if (isBoolean(L, -1)) { - forceLoad = getBoolean(L, -1); - key = getString(L, -2); + auto key = Lua::getString(L, -1); + if (Lua::isBoolean(L, -1)) { + forceLoad = Lua::getBoolean(L, -1); + key = Lua::getString(L, -2); } - if (isUserdata(L, 1)) { - auto scopedKV = getUserdataShared<KV>(L, 1); + if (Lua::isUserdata(L, 1)) { + const auto &scopedKV = Lua::getUserdataShared<KV>(L, 1); valueWrapper = scopedKV->get(key, forceLoad); } else { valueWrapper = g_kv().get(key, forceLoad); @@ -80,9 +98,9 @@ int KVFunctions::luaKVGet(lua_State* L) { int KVFunctions::luaKVRemove(lua_State* L) { // KV.remove(key) | scopedKV:remove(key) - auto key = getString(L, -1); - if (isUserdata(L, 1)) { - auto scopedKV = getUserdataShared<KV>(L, 1); + const auto key = Lua::getString(L, -1); + if (Lua::isUserdata(L, 1)) { + const auto &scopedKV = Lua::getUserdataShared<KV>(L, 1); scopedKV->remove(key); } else { g_kv().remove(key); @@ -94,14 +112,14 @@ int KVFunctions::luaKVRemove(lua_State* L) { int KVFunctions::luaKVKeys(lua_State* L) { // KV.keys([prefix = ""]) | scopedKV:keys([prefix = ""]) std::unordered_set<std::string> keys; - std::string prefix = ""; + std::string prefix; - if (isString(L, -1)) { - prefix = getString(L, -1); + if (Lua::isString(L, -1)) { + prefix = Lua::getString(L, -1); } - if (isUserdata(L, 1)) { - auto scopedKV = getUserdataShared<KV>(L, 1); + if (Lua::isUserdata(L, 1)) { + const auto &scopedKV = Lua::getUserdataShared<KV>(L, 1); keys = scopedKV->keys(); } else { keys = g_kv().keys(prefix); @@ -110,28 +128,28 @@ int KVFunctions::luaKVKeys(lua_State* L) { int index = 0; lua_createtable(L, static_cast<int>(keys.size()), 0); for (const auto &key : keys) { - pushString(L, key); + Lua::pushString(L, key); lua_rawseti(L, -2, ++index); } return 1; } std::optional<ValueWrapper> KVFunctions::getValueWrapper(lua_State* L) { - if (isBoolean(L, -1)) { - return ValueWrapper(getBoolean(L, -1)); + if (Lua::isBoolean(L, -1)) { + return ValueWrapper(Lua::getBoolean(L, -1)); } - if (isNumber(L, -1)) { - return ValueWrapper(getNumber<double>(L, -1)); + if (Lua::isNumber(L, -1)) { + return ValueWrapper(Lua::getNumber<double>(L, -1)); } - if (isString(L, -1)) { - return ValueWrapper(getString(L, -1)); + if (Lua::isString(L, -1)) { + return ValueWrapper(Lua::getString(L, -1)); } - if (isTable(L, -1) && lua_objlen(L, -1) > 0) { + if (Lua::isTable(L, -1) && lua_objlen(L, -1) > 0) { ArrayType array; for (int i = 1; i <= lua_objlen(L, -1); ++i) { lua_rawgeti(L, -1, i); - auto value = getValueWrapper(L); + const auto &value = getValueWrapper(L); if (!value) { g_logger().warn("[{}] invalid param type", __FUNCTION__); return std::nullopt; @@ -142,22 +160,22 @@ std::optional<ValueWrapper> KVFunctions::getValueWrapper(lua_State* L) { return ValueWrapper(array); } - if (isTable(L, -1)) { + if (Lua::isTable(L, -1)) { MapType map; lua_pushnil(L); while (lua_next(L, -2) != 0) { - auto value = getValueWrapper(L); + const auto &value = getValueWrapper(L); if (!value) { g_logger().warn("[{}] invalid param type", __FUNCTION__); return std::nullopt; } - map[getString(L, -2)] = std::make_shared<ValueWrapper>(value.value()); + map[Lua::getString(L, -2)] = std::make_shared<ValueWrapper>(value.value()); lua_pop(L, 1); } return ValueWrapper(map); } - if (isNil(L, -1)) { + if (Lua::isNil(L, -1)) { return std::nullopt; } @@ -166,7 +184,7 @@ std::optional<ValueWrapper> KVFunctions::getValueWrapper(lua_State* L) { } void KVFunctions::pushStringValue(lua_State* L, const StringType &value) { - pushString(L, value); + Lua::pushString(L, value); } void KVFunctions::pushIntValue(lua_State* L, const IntType &value) { @@ -200,7 +218,7 @@ void KVFunctions::pushValueWrapper(lua_State* L, const ValueWrapper &valueWrappe if constexpr (std::is_same_v<T, StringType>) { pushStringValue(L, arg); } else if constexpr (std::is_same_v<T, BooleanType>) { - pushBoolean(L, arg); + Lua::pushBoolean(L, arg); } else if constexpr (std::is_same_v<T, IntType>) { pushIntValue(L, arg); } else if constexpr (std::is_same_v<T, DoubleType>) { diff --git a/src/lua/functions/core/libs/kv_functions.hpp b/src/lua/functions/core/libs/kv_functions.hpp index 919901df7f8..63f9eb8850b 100644 --- a/src/lua/functions/core/libs/kv_functions.hpp +++ b/src/lua/functions/core/libs/kv_functions.hpp @@ -9,8 +9,6 @@ #pragma once -#include "lua/scripts/luascript.hpp" - class ValueWrapper; #ifndef USE_PRECOMPILED_HEADERS @@ -25,23 +23,9 @@ using MapType = phmap::flat_hash_map<std::string, std::shared_ptr<ValueWrapper>> struct lua_State; -class KVFunctions final : LuaScriptInterface { +class KVFunctions { public: - static void init(lua_State* L) { - registerTable(L, "kv"); - registerMethod(L, "kv", "scoped", KVFunctions::luaKVScoped); - registerMethod(L, "kv", "set", KVFunctions::luaKVSet); - registerMethod(L, "kv", "get", KVFunctions::luaKVGet); - registerMethod(L, "kv", "keys", KVFunctions::luaKVKeys); - registerMethod(L, "kv", "remove", KVFunctions::luaKVRemove); - - registerClass(L, "KV", ""); - registerMethod(L, "KV", "scoped", KVFunctions::luaKVScoped); - registerMethod(L, "KV", "set", KVFunctions::luaKVSet); - registerMethod(L, "KV", "get", KVFunctions::luaKVGet); - registerMethod(L, "KV", "keys", KVFunctions::luaKVKeys); - registerMethod(L, "KV", "remove", KVFunctions::luaKVRemove); - } + static void init(lua_State* L); private: static int luaKVScoped(lua_State* L); diff --git a/src/lua/functions/core/libs/logger_functions.cpp b/src/lua/functions/core/libs/logger_functions.cpp index 741d35fec9d..c54f534813a 100644 --- a/src/lua/functions/core/libs/logger_functions.cpp +++ b/src/lua/functions/core/libs/logger_functions.cpp @@ -8,27 +8,28 @@ */ #include "lua/functions/core/libs/logger_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" void LoggerFunctions::init(lua_State* L) { // Kept for compatibility purposes only, it's deprecated - registerTable(L, "Spdlog"); - registerMethod(L, "Spdlog", "info", LoggerFunctions::luaSpdlogInfo); - registerMethod(L, "Spdlog", "warn", LoggerFunctions::luaSpdlogWarn); - registerMethod(L, "Spdlog", "error", LoggerFunctions::luaSpdlogError); - registerMethod(L, "Spdlog", "debug", LoggerFunctions::luaSpdlogDebug); + Lua::registerTable(L, "Spdlog"); + Lua::registerMethod(L, "Spdlog", "info", LoggerFunctions::luaSpdlogInfo); + Lua::registerMethod(L, "Spdlog", "warn", LoggerFunctions::luaSpdlogWarn); + Lua::registerMethod(L, "Spdlog", "error", LoggerFunctions::luaSpdlogError); + Lua::registerMethod(L, "Spdlog", "debug", LoggerFunctions::luaSpdlogDebug); - registerTable(L, "logger"); - registerMethod(L, "logger", "info", LoggerFunctions::luaLoggerInfo); - registerMethod(L, "logger", "warn", LoggerFunctions::luaLoggerWarn); - registerMethod(L, "logger", "error", LoggerFunctions::luaLoggerError); - registerMethod(L, "logger", "debug", LoggerFunctions::luaLoggerDebug); - registerMethod(L, "logger", "trace", LoggerFunctions::luaLoggerTrace); + Lua::registerTable(L, "logger"); + Lua::registerMethod(L, "logger", "info", LoggerFunctions::luaLoggerInfo); + Lua::registerMethod(L, "logger", "warn", LoggerFunctions::luaLoggerWarn); + Lua::registerMethod(L, "logger", "error", LoggerFunctions::luaLoggerError); + Lua::registerMethod(L, "logger", "debug", LoggerFunctions::luaLoggerDebug); + Lua::registerMethod(L, "logger", "trace", LoggerFunctions::luaLoggerTrace); } int LoggerFunctions::luaSpdlogInfo(lua_State* L) { // Spdlog.info(text) - if (isString(L, 1)) { - g_logger().info(getString(L, 1)); + if (Lua::isString(L, 1)) { + g_logger().info(Lua::getString(L, 1)); } else { lua_pushnil(L); } @@ -37,8 +38,8 @@ int LoggerFunctions::luaSpdlogInfo(lua_State* L) { int LoggerFunctions::luaSpdlogWarn(lua_State* L) { // Spdlog.warn(text) - if (isString(L, 1)) { - g_logger().warn(getString(L, 1)); + if (Lua::isString(L, 1)) { + g_logger().warn(Lua::getString(L, 1)); } else { lua_pushnil(L); } @@ -47,8 +48,8 @@ int LoggerFunctions::luaSpdlogWarn(lua_State* L) { int LoggerFunctions::luaSpdlogError(lua_State* L) { // Spdlog.error(text) - if (isString(L, 1)) { - g_logger().error(getString(L, 1)); + if (Lua::isString(L, 1)) { + g_logger().error(Lua::getString(L, 1)); } else { lua_pushnil(L); } @@ -57,8 +58,8 @@ int LoggerFunctions::luaSpdlogError(lua_State* L) { int LoggerFunctions::luaSpdlogDebug(lua_State* L) { // Spdlog.debug(text) - if (isString(L, 1)) { - g_logger().debug(getString(L, 1)); + if (Lua::isString(L, 1)) { + g_logger().debug(Lua::getString(L, 1)); } else { lua_pushnil(L); } @@ -68,30 +69,30 @@ int LoggerFunctions::luaSpdlogDebug(lua_State* L) { // Logger int LoggerFunctions::luaLoggerInfo(lua_State* L) { // logger.info(text) - if (isString(L, 1)) { - g_logger().info(getFormatedLoggerMessage(L)); + if (Lua::isString(L, 1)) { + g_logger().info(Lua::getFormatedLoggerMessage(L)); } else { - reportErrorFunc("First parameter needs to be a string"); + Lua::reportErrorFunc("First parameter needs to be a string"); } return 1; } int LoggerFunctions::luaLoggerWarn(lua_State* L) { // logger.warn(text) - if (isString(L, 1)) { - g_logger().warn(getFormatedLoggerMessage(L)); + if (Lua::isString(L, 1)) { + g_logger().warn(Lua::getFormatedLoggerMessage(L)); } else { - reportErrorFunc("First parameter needs to be a string"); + Lua::reportErrorFunc("First parameter needs to be a string"); } return 1; } int LoggerFunctions::luaLoggerError(lua_State* L) { // logger.error(text) - if (isString(L, 1)) { - g_logger().error(getFormatedLoggerMessage(L)); + if (Lua::isString(L, 1)) { + g_logger().error(Lua::getFormatedLoggerMessage(L)); } else { - reportErrorFunc("First parameter needs to be a string"); + Lua::reportErrorFunc("First parameter needs to be a string"); } return 1; @@ -99,20 +100,20 @@ int LoggerFunctions::luaLoggerError(lua_State* L) { int LoggerFunctions::luaLoggerDebug(lua_State* L) { // logger.debug(text) - if (isString(L, 1)) { - g_logger().debug(getFormatedLoggerMessage(L)); + if (Lua::isString(L, 1)) { + g_logger().debug(Lua::getFormatedLoggerMessage(L)); } else { - reportErrorFunc("First parameter needs to be a string"); + Lua::reportErrorFunc("First parameter needs to be a string"); } return 1; } int LoggerFunctions::luaLoggerTrace(lua_State* L) { // logger.trace(text) - if (isString(L, 1)) { - g_logger().trace(getFormatedLoggerMessage(L)); + if (Lua::isString(L, 1)) { + g_logger().trace(Lua::getFormatedLoggerMessage(L)); } else { - reportErrorFunc("First parameter needs to be a string"); + Lua::reportErrorFunc("First parameter needs to be a string"); } return 1; } diff --git a/src/lua/functions/core/libs/logger_functions.hpp b/src/lua/functions/core/libs/logger_functions.hpp index 2c4dba46cc1..aa5b4d3f80c 100644 --- a/src/lua/functions/core/libs/logger_functions.hpp +++ b/src/lua/functions/core/libs/logger_functions.hpp @@ -9,9 +9,7 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class LoggerFunctions final : public LuaScriptInterface { +class LoggerFunctions { public: static void init(lua_State* L); diff --git a/src/lua/functions/core/libs/metrics_functions.cpp b/src/lua/functions/core/libs/metrics_functions.cpp index bcb233bb5aa..919f39da07e 100644 --- a/src/lua/functions/core/libs/metrics_functions.cpp +++ b/src/lua/functions/core/libs/metrics_functions.cpp @@ -8,29 +8,31 @@ */ #include "lua/functions/core/libs/metrics_functions.hpp" + #include "lib/metrics/metrics.hpp" +#include "lua/functions/lua_functions_loader.hpp" void MetricsFunctions::init(lua_State* L) { - registerTable(L, "metrics"); - registerMethod(L, "metrics", "addCounter", MetricsFunctions::luaMetricsAddCounter); + Lua::registerTable(L, "metrics"); + Lua::registerMethod(L, "metrics", "addCounter", MetricsFunctions::luaMetricsAddCounter); } // Metrics int MetricsFunctions::luaMetricsAddCounter(lua_State* L) { // metrics.addCounter(name, value, attributes) - auto name = getString(L, 1); - auto value = getNumber<double>(L, 2); - auto attributes = getAttributes(L, 3); + const auto name = Lua::getString(L, 1); + const auto value = Lua::getNumber<double>(L, 2); + const auto attributes = getAttributes(L, 3); g_metrics().addCounter(name, value, attributes); return 1; } std::map<std::string, std::string> MetricsFunctions::getAttributes(lua_State* L, int32_t index) { std::map<std::string, std::string> attributes; - if (isTable(L, index)) { + if (Lua::isTable(L, index)) { lua_pushnil(L); while (lua_next(L, index) != 0) { - attributes[getString(L, -2)] = getString(L, -1); + attributes[Lua::getString(L, -2)] = Lua::getString(L, -1); lua_pop(L, 1); } } diff --git a/src/lua/functions/core/libs/metrics_functions.hpp b/src/lua/functions/core/libs/metrics_functions.hpp index e71f005aaa8..8b375244476 100644 --- a/src/lua/functions/core/libs/metrics_functions.hpp +++ b/src/lua/functions/core/libs/metrics_functions.hpp @@ -9,9 +9,7 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class MetricsFunctions final : public LuaScriptInterface { +class MetricsFunctions { public: static void init(lua_State* L); diff --git a/src/lua/functions/core/libs/result_functions.cpp b/src/lua/functions/core/libs/result_functions.cpp index 46acc07af9f..eda7bbad332 100644 --- a/src/lua/functions/core/libs/result_functions.cpp +++ b/src/lua/functions/core/libs/result_functions.cpp @@ -8,57 +8,67 @@ */ #include "lua/functions/core/libs/result_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ResultFunctions::init(lua_State* L) { + Lua::registerTable(L, "Result"); + Lua::registerMethod(L, "Result", "getNumber", ResultFunctions::luaResultGetNumber); + Lua::registerMethod(L, "Result", "getString", ResultFunctions::luaResultGetString); + Lua::registerMethod(L, "Result", "getStream", ResultFunctions::luaResultGetStream); + Lua::registerMethod(L, "Result", "next", ResultFunctions::luaResultNext); + Lua::registerMethod(L, "Result", "free", ResultFunctions::luaResultFree); +} int ResultFunctions::luaResultGetNumber(lua_State* L) { - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1)); + const auto &res = ScriptEnvironment::getResultByID(Lua::getNumber<uint32_t>(L, 1)); if (!res) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - const std::string &s = getString(L, 2); + const std::string &s = Lua::getString(L, 2); lua_pushnumber(L, res->getNumber<int64_t>(s)); return 1; } int ResultFunctions::luaResultGetString(lua_State* L) { - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1)); + const auto &res = ScriptEnvironment::getResultByID(Lua::getNumber<uint32_t>(L, 1)); if (!res) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - const std::string &s = getString(L, 2); - pushString(L, res->getString(s)); + const std::string &s = Lua::getString(L, 2); + Lua::pushString(L, res->getString(s)); return 1; } int ResultFunctions::luaResultGetStream(lua_State* L) { - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1)); + const auto &res = ScriptEnvironment::getResultByID(Lua::getNumber<uint32_t>(L, 1)); if (!res) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } unsigned long length; - const char* stream = res->getStream(getString(L, 2), length); + const char* stream = res->getStream(Lua::getString(L, 2), length); lua_pushlstring(L, stream, length); lua_pushnumber(L, length); return 2; } int ResultFunctions::luaResultNext(lua_State* L) { - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, -1)); + const auto &res = ScriptEnvironment::getResultByID(Lua::getNumber<uint32_t>(L, -1)); if (!res) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, res->next()); + Lua::pushBoolean(L, res->next()); return 1; } int ResultFunctions::luaResultFree(lua_State* L) { - pushBoolean(L, ScriptEnvironment::removeResult(getNumber<uint32_t>(L, -1))); + Lua::pushBoolean(L, ScriptEnvironment::removeResult(Lua::getNumber<uint32_t>(L, -1))); return 1; } diff --git a/src/lua/functions/core/libs/result_functions.hpp b/src/lua/functions/core/libs/result_functions.hpp index 4aa25173ed7..3b979da3c86 100644 --- a/src/lua/functions/core/libs/result_functions.hpp +++ b/src/lua/functions/core/libs/result_functions.hpp @@ -9,18 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ResultFunctions final : LuaScriptInterface { +class ResultFunctions { public: - static void init(lua_State* L) { - registerTable(L, "Result"); - registerMethod(L, "Result", "getNumber", ResultFunctions::luaResultGetNumber); - registerMethod(L, "Result", "getString", ResultFunctions::luaResultGetString); - registerMethod(L, "Result", "getStream", ResultFunctions::luaResultGetStream); - registerMethod(L, "Result", "next", ResultFunctions::luaResultNext); - registerMethod(L, "Result", "free", ResultFunctions::luaResultFree); - } + static void init(lua_State* L); private: static int luaResultFree(lua_State* L); diff --git a/src/lua/functions/core/network/core_network_functions.hpp b/src/lua/functions/core/network/core_network_functions.hpp index c1e65ec15ac..8f0c3b021ef 100644 --- a/src/lua/functions/core/network/core_network_functions.hpp +++ b/src/lua/functions/core/network/core_network_functions.hpp @@ -15,6 +15,12 @@ class CoreNetworkFunctions final : LuaScriptInterface { public: + explicit CoreNetworkFunctions(lua_State* L) : + LuaScriptInterface("CoreNetworkFunctions") { + init(L); + } + ~CoreNetworkFunctions() override = default; + static void init(lua_State* L) { NetworkMessageFunctions::init(L); WebhookFunctions::init(L); diff --git a/src/lua/functions/core/network/network_message_functions.cpp b/src/lua/functions/core/network/network_message_functions.cpp index c7572b4488b..bfd3b86897e 100644 --- a/src/lua/functions/core/network/network_message_functions.cpp +++ b/src/lua/functions/core/network/network_message_functions.cpp @@ -8,19 +8,52 @@ */ #include "lua/functions/core/network/network_message_functions.hpp" + +#include "server/network/protocol/protocolgame.hpp" #include "creatures/players/player.hpp" #include "server/network/protocol/protocolstatus.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void NetworkMessageFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "NetworkMessage", "", NetworkMessageFunctions::luaNetworkMessageCreate); + Lua::registerMetaMethod(L, "NetworkMessage", "__eq", Lua::luaUserdataCompare); + Lua::registerMethod(L, "NetworkMessage", "delete", Lua::luaGarbageCollection); + + Lua::registerMethod(L, "NetworkMessage", "getByte", NetworkMessageFunctions::luaNetworkMessageGetByte); + Lua::registerMethod(L, "NetworkMessage", "getU16", NetworkMessageFunctions::luaNetworkMessageGetU16); + Lua::registerMethod(L, "NetworkMessage", "getU32", NetworkMessageFunctions::luaNetworkMessageGetU32); + Lua::registerMethod(L, "NetworkMessage", "getU64", NetworkMessageFunctions::luaNetworkMessageGetU64); + Lua::registerMethod(L, "NetworkMessage", "getString", NetworkMessageFunctions::luaNetworkMessageGetString); + Lua::registerMethod(L, "NetworkMessage", "getPosition", NetworkMessageFunctions::luaNetworkMessageGetPosition); + + Lua::registerMethod(L, "NetworkMessage", "addByte", NetworkMessageFunctions::luaNetworkMessageAddByte); + Lua::registerMethod(L, "NetworkMessage", "addU16", NetworkMessageFunctions::luaNetworkMessageAddU16); + Lua::registerMethod(L, "NetworkMessage", "addU32", NetworkMessageFunctions::luaNetworkMessageAddU32); + Lua::registerMethod(L, "NetworkMessage", "addU64", NetworkMessageFunctions::luaNetworkMessageAddU64); + Lua::registerMethod(L, "NetworkMessage", "add8", NetworkMessageFunctions::luaNetworkMessageAdd8); + Lua::registerMethod(L, "NetworkMessage", "add16", NetworkMessageFunctions::luaNetworkMessageAdd16); + Lua::registerMethod(L, "NetworkMessage", "add32", NetworkMessageFunctions::luaNetworkMessageAdd32); + Lua::registerMethod(L, "NetworkMessage", "add64", NetworkMessageFunctions::luaNetworkMessageAdd64); + Lua::registerMethod(L, "NetworkMessage", "addString", NetworkMessageFunctions::luaNetworkMessageAddString); + Lua::registerMethod(L, "NetworkMessage", "addPosition", NetworkMessageFunctions::luaNetworkMessageAddPosition); + Lua::registerMethod(L, "NetworkMessage", "addDouble", NetworkMessageFunctions::luaNetworkMessageAddDouble); + Lua::registerMethod(L, "NetworkMessage", "addItem", NetworkMessageFunctions::luaNetworkMessageAddItem); + + Lua::registerMethod(L, "NetworkMessage", "reset", NetworkMessageFunctions::luaNetworkMessageReset); + Lua::registerMethod(L, "NetworkMessage", "skipBytes", NetworkMessageFunctions::luaNetworkMessageSkipBytes); + Lua::registerMethod(L, "NetworkMessage", "sendToPlayer", NetworkMessageFunctions::luaNetworkMessageSendToPlayer); +} int NetworkMessageFunctions::luaNetworkMessageCreate(lua_State* L) { // NetworkMessage() - pushUserdata<NetworkMessage>(L, std::make_shared<NetworkMessage>()); - setMetatable(L, -1, "NetworkMessage"); + Lua::pushUserdata<NetworkMessage>(L, std::make_shared<NetworkMessage>()); + Lua::setMetatable(L, -1, "NetworkMessage"); return 1; } int NetworkMessageFunctions::luaNetworkMessageGetByte(lua_State* L) { // networkMessage:getByte() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { lua_pushnumber(L, message->getByte()); } else { @@ -31,7 +64,7 @@ int NetworkMessageFunctions::luaNetworkMessageGetByte(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageGetU16(lua_State* L) { // networkMessage:getU16() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { lua_pushnumber(L, message->get<uint16_t>()); } else { @@ -42,7 +75,7 @@ int NetworkMessageFunctions::luaNetworkMessageGetU16(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageGetU32(lua_State* L) { // networkMessage:getU32() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { lua_pushnumber(L, message->get<uint32_t>()); } else { @@ -53,7 +86,7 @@ int NetworkMessageFunctions::luaNetworkMessageGetU32(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageGetU64(lua_State* L) { // networkMessage:getU64() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { lua_pushnumber(L, message->get<uint64_t>()); } else { @@ -63,10 +96,10 @@ int NetworkMessageFunctions::luaNetworkMessageGetU64(lua_State* L) { } int NetworkMessageFunctions::luaNetworkMessageGetString(lua_State* L) { - // networkMessage:getString() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + // networkMessage:Lua::getString() + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { - pushString(L, message->getString()); + Lua::pushString(L, message->getString()); } else { lua_pushnil(L); } @@ -74,10 +107,10 @@ int NetworkMessageFunctions::luaNetworkMessageGetString(lua_State* L) { } int NetworkMessageFunctions::luaNetworkMessageGetPosition(lua_State* L) { - // networkMessage:getPosition() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + // networkMessage:Lua::getPosition() + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { - pushPosition(L, message->getPosition()); + Lua::pushPosition(L, message->getPosition()); } else { lua_pushnil(L); } @@ -86,11 +119,11 @@ int NetworkMessageFunctions::luaNetworkMessageGetPosition(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddByte(lua_State* L) { // networkMessage:addByte(number) - uint8_t number = getNumber<uint8_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const uint8_t number = Lua::getNumber<uint8_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->addByte(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -99,11 +132,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddByte(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddU16(lua_State* L) { // networkMessage:addU16(number) - uint16_t number = getNumber<uint16_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const uint16_t number = Lua::getNumber<uint16_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<uint16_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -112,11 +145,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddU16(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddU32(lua_State* L) { // networkMessage:addU32(number) - uint32_t number = getNumber<uint32_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const uint32_t number = Lua::getNumber<uint32_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<uint32_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -125,11 +158,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddU32(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddU64(lua_State* L) { // networkMessage:addU64(number) - uint64_t number = getNumber<uint64_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const uint64_t number = Lua::getNumber<uint64_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<uint64_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -138,11 +171,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddU64(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAdd8(lua_State* L) { // networkMessage:add8(number) - auto number = getNumber<int8_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto number = Lua::getNumber<int8_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<int8_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -151,11 +184,11 @@ int NetworkMessageFunctions::luaNetworkMessageAdd8(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAdd16(lua_State* L) { // networkMessage:add16(number) - auto number = getNumber<int16_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto number = Lua::getNumber<int16_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<int16_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -164,11 +197,11 @@ int NetworkMessageFunctions::luaNetworkMessageAdd16(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAdd32(lua_State* L) { // networkMessage:add32(number) - auto number = getNumber<int32_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto number = Lua::getNumber<int32_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<int32_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -177,11 +210,11 @@ int NetworkMessageFunctions::luaNetworkMessageAdd32(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAdd64(lua_State* L) { // networkMessage:add64(number) - auto number = getNumber<int64_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto number = Lua::getNumber<int64_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->add<int64_t>(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -190,12 +223,12 @@ int NetworkMessageFunctions::luaNetworkMessageAdd64(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddString(lua_State* L) { // networkMessage:addString(string, function) - const std::string &string = getString(L, 2); - const std::string &function = getString(L, 3); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const std::string &string = Lua::getString(L, 2); + const std::string &function = Lua::getString(L, 3); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->addString(string, std::source_location::current(), function); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -204,11 +237,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddString(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddPosition(lua_State* L) { // networkMessage:addPosition(position) - const Position &position = getPosition(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const Position &position = Lua::getPosition(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->addPosition(position); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -217,11 +250,11 @@ int NetworkMessageFunctions::luaNetworkMessageAddPosition(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddDouble(lua_State* L) { // networkMessage:addDouble(number) - double number = getNumber<double>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const double number = Lua::getNumber<double>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->addDouble(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -230,24 +263,24 @@ int NetworkMessageFunctions::luaNetworkMessageAddDouble(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageAddItem(lua_State* L) { // networkMessage:addItem(item, player) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); lua_pushnil(L); return 1; } - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 3); + const auto &player = Lua::getUserdataShared<Player>(L, 3); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message && player->client) { player->client->AddItem(*message, item); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -256,10 +289,10 @@ int NetworkMessageFunctions::luaNetworkMessageAddItem(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageReset(lua_State* L) { // networkMessage:reset() - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->reset(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -268,11 +301,11 @@ int NetworkMessageFunctions::luaNetworkMessageReset(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageSkipBytes(lua_State* L) { // networkMessage:skipBytes(number) - int16_t number = getNumber<int16_t>(L, 2); - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const int16_t number = Lua::getNumber<int16_t>(L, 2); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (message) { message->skipBytes(number); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -281,19 +314,19 @@ int NetworkMessageFunctions::luaNetworkMessageSkipBytes(lua_State* L) { int NetworkMessageFunctions::luaNetworkMessageSendToPlayer(lua_State* L) { // networkMessage:sendToPlayer(player) - const auto &message = getUserdataShared<NetworkMessage>(L, 1); + const auto &message = Lua::getUserdataShared<NetworkMessage>(L, 1); if (!message) { lua_pushnil(L); return 1; } - std::shared_ptr<Player> player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } player->sendNetworkMessage(*message); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/core/network/network_message_functions.hpp b/src/lua/functions/core/network/network_message_functions.hpp index 5a2982c0d85..906d649f7ea 100644 --- a/src/lua/functions/core/network/network_message_functions.hpp +++ b/src/lua/functions/core/network/network_message_functions.hpp @@ -9,39 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class NetworkMessageFunctions final : LuaScriptInterface { +class NetworkMessageFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "NetworkMessage", "", NetworkMessageFunctions::luaNetworkMessageCreate); - registerMetaMethod(L, "NetworkMessage", "__eq", NetworkMessageFunctions::luaUserdataCompare); - registerMethod(L, "NetworkMessage", "delete", luaGarbageCollection); - - registerMethod(L, "NetworkMessage", "getByte", NetworkMessageFunctions::luaNetworkMessageGetByte); - registerMethod(L, "NetworkMessage", "getU16", NetworkMessageFunctions::luaNetworkMessageGetU16); - registerMethod(L, "NetworkMessage", "getU32", NetworkMessageFunctions::luaNetworkMessageGetU32); - registerMethod(L, "NetworkMessage", "getU64", NetworkMessageFunctions::luaNetworkMessageGetU64); - registerMethod(L, "NetworkMessage", "getString", NetworkMessageFunctions::luaNetworkMessageGetString); - registerMethod(L, "NetworkMessage", "getPosition", NetworkMessageFunctions::luaNetworkMessageGetPosition); - - registerMethod(L, "NetworkMessage", "addByte", NetworkMessageFunctions::luaNetworkMessageAddByte); - registerMethod(L, "NetworkMessage", "addU16", NetworkMessageFunctions::luaNetworkMessageAddU16); - registerMethod(L, "NetworkMessage", "addU32", NetworkMessageFunctions::luaNetworkMessageAddU32); - registerMethod(L, "NetworkMessage", "addU64", NetworkMessageFunctions::luaNetworkMessageAddU64); - registerMethod(L, "NetworkMessage", "add8", NetworkMessageFunctions::luaNetworkMessageAdd8); - registerMethod(L, "NetworkMessage", "add16", NetworkMessageFunctions::luaNetworkMessageAdd16); - registerMethod(L, "NetworkMessage", "add32", NetworkMessageFunctions::luaNetworkMessageAdd32); - registerMethod(L, "NetworkMessage", "add64", NetworkMessageFunctions::luaNetworkMessageAdd64); - registerMethod(L, "NetworkMessage", "addString", NetworkMessageFunctions::luaNetworkMessageAddString); - registerMethod(L, "NetworkMessage", "addPosition", NetworkMessageFunctions::luaNetworkMessageAddPosition); - registerMethod(L, "NetworkMessage", "addDouble", NetworkMessageFunctions::luaNetworkMessageAddDouble); - registerMethod(L, "NetworkMessage", "addItem", NetworkMessageFunctions::luaNetworkMessageAddItem); - - registerMethod(L, "NetworkMessage", "reset", NetworkMessageFunctions::luaNetworkMessageReset); - registerMethod(L, "NetworkMessage", "skipBytes", NetworkMessageFunctions::luaNetworkMessageSkipBytes); - registerMethod(L, "NetworkMessage", "sendToPlayer", NetworkMessageFunctions::luaNetworkMessageSendToPlayer); - } + static void init(lua_State* L); private: static int luaNetworkMessageCreate(lua_State* L); diff --git a/src/lua/functions/core/network/webhook_functions.cpp b/src/lua/functions/core/network/webhook_functions.cpp index b24e6184ce3..7a55b656a74 100644 --- a/src/lua/functions/core/network/webhook_functions.cpp +++ b/src/lua/functions/core/network/webhook_functions.cpp @@ -8,15 +8,22 @@ */ #include "lua/functions/core/network/webhook_functions.hpp" + #include "server/network/webhook/webhook.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void WebhookFunctions::init(lua_State* L) { + Lua::registerTable(L, "Webhook"); + Lua::registerMethod(L, "Webhook", "sendMessage", WebhookFunctions::luaWebhookSendMessage); +} int WebhookFunctions::luaWebhookSendMessage(lua_State* L) { // Webhook.sendMessage(title, message, color, url = "WEBHOOK_DISCORD_URL") | // Webhook.sendMessage(message, url = "WEBHOOK_DISCORD_URL") - std::string title = getString(L, 1); - std::string message = getString(L, 2); - uint32_t color = getNumber<uint32_t>(L, 3, 0); - std::string url = getString(L, -1); + const std::string title = Lua::getString(L, 1); + const std::string message = Lua::getString(L, 2); + const auto color = Lua::getNumber<uint32_t>(L, 3, 0); + const std::string url = Lua::getString(L, -1); if (url == title) { g_webhook().sendMessage(title); } else if (url == message) { diff --git a/src/lua/functions/core/network/webhook_functions.hpp b/src/lua/functions/core/network/webhook_functions.hpp index 7d5f53ba4b8..c7f24115520 100644 --- a/src/lua/functions/core/network/webhook_functions.hpp +++ b/src/lua/functions/core/network/webhook_functions.hpp @@ -9,14 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class WebhookFunctions final : LuaScriptInterface { +class WebhookFunctions { public: - static void init(lua_State* L) { - registerTable(L, "Webhook"); - registerMethod(L, "Webhook", "sendMessage", WebhookFunctions::luaWebhookSendMessage); - } + static void init(lua_State* L); private: static int luaWebhookSendMessage(lua_State* L); diff --git a/src/lua/functions/creatures/combat/combat_functions.cpp b/src/lua/functions/creatures/combat/combat_functions.cpp index f073cde6aba..776f447952e 100644 --- a/src/lua/functions/creatures/combat/combat_functions.cpp +++ b/src/lua/functions/creatures/combat/combat_functions.cpp @@ -7,77 +7,102 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/combat/combat_functions.hpp" + +#include "creatures/creature.hpp" #include "creatures/combat/combat.hpp" +#include "creatures/combat/condition.hpp" #include "game/game.hpp" -#include "lua/functions/creatures/combat/combat_functions.hpp" -#include "lua/scripts/lua_environment.hpp" #include "lua/global/lua_variant.hpp" +#include "lua/scripts/lua_environment.hpp" +#include "creatures/players/player.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void CombatFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Combat", "", CombatFunctions::luaCombatCreate); + Lua::registerMetaMethod(L, "Combat", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Combat", "setParameter", CombatFunctions::luaCombatSetParameter); + Lua::registerMethod(L, "Combat", "setFormula", CombatFunctions::luaCombatSetFormula); + + Lua::registerMethod(L, "Combat", "setArea", CombatFunctions::luaCombatSetArea); + Lua::registerMethod(L, "Combat", "addCondition", CombatFunctions::luaCombatSetCondition); + Lua::registerMethod(L, "Combat", "setCallback", CombatFunctions::luaCombatSetCallback); + Lua::registerMethod(L, "Combat", "setOrigin", CombatFunctions::luaCombatSetOrigin); + + Lua::registerMethod(L, "Combat", "execute", CombatFunctions::luaCombatExecute); + + ConditionFunctions::init(L); + SpellFunctions::init(L); + VariantFunctions::init(L); +} int CombatFunctions::luaCombatCreate(lua_State* L) { // Combat() - pushUserdata<Combat>(L, g_luaEnvironment().createCombatObject(getScriptEnv()->getScriptInterface())); - setMetatable(L, -1, "Combat"); + auto combat = std::make_shared<Combat>(); + Lua::pushUserdata<Combat>(L, combat); + Lua::setMetatable(L, -1, "Combat"); return 1; } int CombatFunctions::luaCombatSetParameter(lua_State* L) { // combat:setParameter(key, value) - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (!combat) { lua_pushnil(L); return 1; } - CombatParam_t key = getNumber<CombatParam_t>(L, 2); + const CombatParam_t key = Lua::getNumber<CombatParam_t>(L, 2); uint32_t value; - if (isBoolean(L, 3)) { - value = getBoolean(L, 3) ? 1 : 0; + if (Lua::isBoolean(L, 3)) { + value = Lua::getBoolean(L, 3) ? 1 : 0; } else { - value = getNumber<uint32_t>(L, 3); + value = Lua::getNumber<uint32_t>(L, 3); } combat->setParam(key, value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CombatFunctions::luaCombatSetFormula(lua_State* L) { // combat:setFormula(type, mina, minb, maxa, maxb) - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (!combat) { lua_pushnil(L); return 1; } - formulaType_t type = getNumber<formulaType_t>(L, 2); - double mina = getNumber<double>(L, 3); - double minb = getNumber<double>(L, 4); - double maxa = getNumber<double>(L, 5); - double maxb = getNumber<double>(L, 6); + const formulaType_t type = Lua::getNumber<formulaType_t>(L, 2); + const double mina = Lua::getNumber<double>(L, 3); + const double minb = Lua::getNumber<double>(L, 4); + const double maxa = Lua::getNumber<double>(L, 5); + const double maxb = Lua::getNumber<double>(L, 6); combat->setPlayerCombatValues(type, mina, minb, maxa, maxb); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CombatFunctions::luaCombatSetArea(lua_State* L) { // combat:setArea(area) - if (getScriptEnv()->getScriptId() != EVENT_ID_LOADING) { - reportErrorFunc("This function can only be used while loading the script."); + if (Lua::getScriptEnv()->getScriptId() != EVENT_ID_LOADING) { + Lua::reportErrorFunc("This function can only be used while loading the script."); lua_pushnil(L); return 1; } - const std::unique_ptr<AreaCombat> &area = g_luaEnvironment().getAreaObject(getNumber<uint32_t>(L, 2)); + const std::unique_ptr<AreaCombat> &area = g_luaEnvironment().getAreaObject(Lua::getNumber<uint32_t>(L, 2)); if (!area) { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); lua_pushnil(L); return 1; } - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (combat) { auto areaClone = area->clone(); combat->setArea(areaClone); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -86,11 +111,11 @@ int CombatFunctions::luaCombatSetArea(lua_State* L) { int CombatFunctions::luaCombatSetCondition(lua_State* L) { // combat:addCondition(condition) - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 2); - Combat* combat = getUserdata<Combat>(L, 1); + const std::shared_ptr<Condition> &condition = Lua::getUserdataShared<Condition>(L, 2); + auto* combat = Lua::getUserdata<Combat>(L, 1); if (combat && condition) { combat->addCondition(condition->clone()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -99,13 +124,13 @@ int CombatFunctions::luaCombatSetCondition(lua_State* L) { int CombatFunctions::luaCombatSetCallback(lua_State* L) { // combat:setCallback(key, function) - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (!combat) { lua_pushnil(L); return 1; } - CallBackParam_t key = getNumber<CallBackParam_t>(L, 2); + const CallBackParam_t key = Lua::getNumber<CallBackParam_t>(L, 2); if (!combat->setCallback(key)) { lua_pushnil(L); return 1; @@ -117,17 +142,17 @@ int CombatFunctions::luaCombatSetCallback(lua_State* L) { return 1; } - const std::string &function = getString(L, 3); - pushBoolean(L, callback->loadCallBack(getScriptEnv()->getScriptInterface(), function)); + const std::string &function = Lua::getString(L, 3); + Lua::pushBoolean(L, callback->loadCallBack(Lua::getScriptEnv()->getScriptInterface(), function)); return 1; } int CombatFunctions::luaCombatSetOrigin(lua_State* L) { // combat:setOrigin(origin) - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (combat) { - combat->setOrigin(getNumber<CombatOrigin>(L, 2)); - pushBoolean(L, true); + combat->setOrigin(Lua::getNumber<CombatOrigin>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -136,31 +161,36 @@ int CombatFunctions::luaCombatSetOrigin(lua_State* L) { int CombatFunctions::luaCombatExecute(lua_State* L) { // combat:execute(creature, variant) - const auto &combat = getUserdataShared<Combat>(L, 1); + const auto &combat = Lua::getUserdataShared<Combat>(L, 1); if (!combat) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - if (isUserdata(L, 2)) { - LuaData_t type = getUserdataType(L, 2); - if (type != LuaData_t::Player && type != LuaData_t::Monster && type != LuaData_t::Npc) { - pushBoolean(L, false); + if (Lua::isUserdata(L, 2)) { + using enum LuaData_t; + const LuaData_t type = Lua::getUserdataType(L, 2); + if (type != Player && type != Monster && type != Npc) { + Lua::pushBoolean(L, false); return 1; } } - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &creature = Lua::getCreature(L, 2); + if (!creature) { + Lua::pushBoolean(L, false); + return 1; + } - const LuaVariant &variant = getVariant(L, 3); + const LuaVariant &variant = Lua::getVariant(L, 3); combat->setInstantSpellName(variant.instantName); combat->setRuneSpellName(variant.runeName); bool result = true; switch (variant.type) { case VARIANT_NUMBER: { - std::shared_ptr<Creature> target = g_game().getCreatureByID(variant.number); + const std::shared_ptr<Creature> &target = g_game().getCreatureByID(variant.number); if (!target) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -188,9 +218,9 @@ int CombatFunctions::luaCombatExecute(lua_State* L) { } case VARIANT_STRING: { - std::shared_ptr<Player> target = g_game().getPlayerByName(variant.text); + const std::shared_ptr<Player> &target = g_game().getPlayerByName(variant.text); if (!target) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -199,8 +229,8 @@ int CombatFunctions::luaCombatExecute(lua_State* L) { } case VARIANT_NONE: { - reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -209,6 +239,6 @@ int CombatFunctions::luaCombatExecute(lua_State* L) { } } - pushBoolean(L, result); + Lua::pushBoolean(L, result); return 1; } diff --git a/src/lua/functions/creatures/combat/combat_functions.hpp b/src/lua/functions/creatures/combat/combat_functions.hpp index e031713e98e..9cf0923eb67 100644 --- a/src/lua/functions/creatures/combat/combat_functions.hpp +++ b/src/lua/functions/creatures/combat/combat_functions.hpp @@ -9,31 +9,13 @@ #pragma once -#include "lua/scripts/luascript.hpp" #include "lua/functions/creatures/combat/condition_functions.hpp" #include "lua/functions/creatures/combat/spell_functions.hpp" #include "lua/functions/creatures/combat/variant_functions.hpp" -class CombatFunctions final : LuaScriptInterface { +class CombatFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Combat", "", CombatFunctions::luaCombatCreate); - registerMetaMethod(L, "Combat", "__eq", CombatFunctions::luaUserdataCompare); - - registerMethod(L, "Combat", "setParameter", CombatFunctions::luaCombatSetParameter); - registerMethod(L, "Combat", "setFormula", CombatFunctions::luaCombatSetFormula); - - registerMethod(L, "Combat", "setArea", CombatFunctions::luaCombatSetArea); - registerMethod(L, "Combat", "addCondition", CombatFunctions::luaCombatSetCondition); - registerMethod(L, "Combat", "setCallback", CombatFunctions::luaCombatSetCallback); - registerMethod(L, "Combat", "setOrigin", CombatFunctions::luaCombatSetOrigin); - - registerMethod(L, "Combat", "execute", CombatFunctions::luaCombatExecute); - - ConditionFunctions::init(L); - SpellFunctions::init(L); - VariantFunctions::init(L); - } + static void init(lua_State* L); private: static int luaCombatCreate(lua_State* L); diff --git a/src/lua/functions/creatures/combat/condition_functions.cpp b/src/lua/functions/creatures/combat/condition_functions.cpp index e7b1dd331ea..0f2f9a56759 100644 --- a/src/lua/functions/creatures/combat/condition_functions.cpp +++ b/src/lua/functions/creatures/combat/condition_functions.cpp @@ -7,26 +7,53 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/combat/condition_functions.hpp" + #include "creatures/combat/condition.hpp" +#include "enums/player_icons.hpp" #include "game/game.hpp" -#include "lua/functions/creatures/combat/condition_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ConditionFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Condition", "", ConditionFunctions::luaConditionCreate); + Lua::registerMetaMethod(L, "Condition", "__eq", Lua::luaUserdataCompare); + Lua::registerMetaMethod(L, "Condition", "__gc", ConditionFunctions::luaConditionDelete); + Lua::registerMethod(L, "Condition", "delete", ConditionFunctions::luaConditionDelete); + + Lua::registerMethod(L, "Condition", "getId", ConditionFunctions::luaConditionGetId); + Lua::registerMethod(L, "Condition", "getSubId", ConditionFunctions::luaConditionGetSubId); + Lua::registerMethod(L, "Condition", "getType", ConditionFunctions::luaConditionGetType); + Lua::registerMethod(L, "Condition", "getIcons", ConditionFunctions::luaConditionGetIcons); + Lua::registerMethod(L, "Condition", "getEndTime", ConditionFunctions::luaConditionGetEndTime); + + Lua::registerMethod(L, "Condition", "clone", ConditionFunctions::luaConditionClone); + + Lua::registerMethod(L, "Condition", "getTicks", ConditionFunctions::luaConditionGetTicks); + Lua::registerMethod(L, "Condition", "setTicks", ConditionFunctions::luaConditionSetTicks); + + Lua::registerMethod(L, "Condition", "setParameter", ConditionFunctions::luaConditionSetParameter); + Lua::registerMethod(L, "Condition", "setFormula", ConditionFunctions::luaConditionSetFormula); + Lua::registerMethod(L, "Condition", "setOutfit", ConditionFunctions::luaConditionSetOutfit); + + Lua::registerMethod(L, "Condition", "addDamage", ConditionFunctions::luaConditionAddDamage); +} int ConditionFunctions::luaConditionCreate(lua_State* L) { // Condition(conditionType, conditionId = CONDITIONID_COMBAT, subid = 0, isPersistent = false) - ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2); + const ConditionType_t conditionType = Lua::getNumber<ConditionType_t>(L, 2); if (conditionType == CONDITION_NONE) { - reportErrorFunc("Invalid condition type"); + Lua::reportErrorFunc("Invalid condition type"); return 1; } - ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); - uint32_t subId = getNumber<uint32_t>(L, 4, 0); - bool isPersistent = getBoolean(L, 5, false); + const auto conditionId = Lua::getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); + const auto subId = Lua::getNumber<uint32_t>(L, 4, 0); + const bool isPersistent = Lua::getBoolean(L, 5, false); - std::shared_ptr<Condition> condition = Condition::createCondition(conditionId, conditionType, 0, 0, false, subId, isPersistent); + const auto &condition = Condition::createCondition(conditionId, conditionType, 0, 0, false, subId, isPersistent); if (condition) { - pushUserdata<Condition>(L, condition); - setMetatable(L, -1, "Condition"); + Lua::pushUserdata<Condition>(L, condition); + Lua::setMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } @@ -35,7 +62,7 @@ int ConditionFunctions::luaConditionCreate(lua_State* L) { int ConditionFunctions::luaConditionDelete(lua_State* L) { // condition:delete() - std::shared_ptr<Condition>* conditionPtr = getRawUserDataShared<Condition>(L, 1); + std::shared_ptr<Condition>* conditionPtr = Lua::getRawUserDataShared<Condition>(L, 1); if (conditionPtr && *conditionPtr) { conditionPtr->reset(); } @@ -44,7 +71,7 @@ int ConditionFunctions::luaConditionDelete(lua_State* L) { int ConditionFunctions::luaConditionGetId(lua_State* L) { // condition:getId() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { lua_pushnumber(L, condition->getId()); } else { @@ -55,7 +82,7 @@ int ConditionFunctions::luaConditionGetId(lua_State* L) { int ConditionFunctions::luaConditionGetSubId(lua_State* L) { // condition:getSubId() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { lua_pushnumber(L, condition->getSubId()); } else { @@ -66,7 +93,7 @@ int ConditionFunctions::luaConditionGetSubId(lua_State* L) { int ConditionFunctions::luaConditionGetType(lua_State* L) { // condition:getType() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { lua_pushnumber(L, condition->getType()); } else { @@ -77,9 +104,9 @@ int ConditionFunctions::luaConditionGetType(lua_State* L) { int ConditionFunctions::luaConditionGetIcons(lua_State* L) { // condition:getIcons() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { - auto icons = condition->getIcons(); + const auto icons = condition->getIcons(); lua_newtable(L); // Creates a new table on the Lua stack int index = 1; for (const auto &icon : icons) { @@ -94,7 +121,7 @@ int ConditionFunctions::luaConditionGetIcons(lua_State* L) { int ConditionFunctions::luaConditionGetEndTime(lua_State* L) { // condition:getEndTime() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { lua_pushnumber(L, condition->getEndTime()); } else { @@ -105,10 +132,10 @@ int ConditionFunctions::luaConditionGetEndTime(lua_State* L) { int ConditionFunctions::luaConditionClone(lua_State* L) { // condition:clone() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { - pushUserdata<Condition>(L, condition->clone()); - setMetatable(L, -1, "Condition"); + Lua::pushUserdata<Condition>(L, condition->clone()); + Lua::setMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } @@ -117,7 +144,7 @@ int ConditionFunctions::luaConditionClone(lua_State* L) { int ConditionFunctions::luaConditionGetTicks(lua_State* L) { // condition:getTicks() - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { lua_pushnumber(L, condition->getTicks()); } else { @@ -128,11 +155,11 @@ int ConditionFunctions::luaConditionGetTicks(lua_State* L) { int ConditionFunctions::luaConditionSetTicks(lua_State* L) { // condition:setTicks(ticks) - int32_t ticks = getNumber<int32_t>(L, 2); - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const int32_t ticks = Lua::getNumber<int32_t>(L, 2); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (condition) { condition->setTicks(ticks); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -141,34 +168,34 @@ int ConditionFunctions::luaConditionSetTicks(lua_State* L) { int ConditionFunctions::luaConditionSetParameter(lua_State* L) { // condition:setParameter(key, value) - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 1); if (!condition) { lua_pushnil(L); return 1; } - ConditionParam_t key = getNumber<ConditionParam_t>(L, 2); + const ConditionParam_t key = Lua::getNumber<ConditionParam_t>(L, 2); int32_t value; - if (isBoolean(L, 3)) { - value = getBoolean(L, 3) ? 1 : 0; + if (Lua::isBoolean(L, 3)) { + value = Lua::getBoolean(L, 3) ? 1 : 0; } else { - value = getNumber<int32_t>(L, 3); + value = Lua::getNumber<int32_t>(L, 3); } condition->setParam(key, value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ConditionFunctions::luaConditionSetFormula(lua_State* L) { // condition:setFormula(mina, minb, maxa, maxb) - double maxb = getNumber<double>(L, 5); - double maxa = getNumber<double>(L, 4); - double minb = getNumber<double>(L, 3); - double mina = getNumber<double>(L, 2); - std::shared_ptr<ConditionSpeed> condition = getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionSpeed>(); + const double maxb = Lua::getNumber<double>(L, 5); + const double maxa = Lua::getNumber<double>(L, 4); + const double minb = Lua::getNumber<double>(L, 3); + const double mina = Lua::getNumber<double>(L, 2); + const std::shared_ptr<ConditionSpeed> &condition = Lua::getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionSpeed>(); if (condition) { condition->setFormulaVars(mina, minb, maxa, maxb); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -180,28 +207,28 @@ int ConditionFunctions::luaConditionSetOutfit(lua_State* L) { // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs, lookFeet[, // lookAddons[, lookMount[, lookMountHead[, lookMountBody[, lookMountLegs[, lookMountFeet[, lookFamiliarsType]]]]]]]) Outfit_t outfit; - if (isTable(L, 2)) { - outfit = getOutfit(L, 2); + if (Lua::isTable(L, 2)) { + outfit = Lua::getOutfit(L, 2); } else { - outfit.lookFamiliarsType = getNumber<uint16_t>(L, 14, outfit.lookFamiliarsType); - outfit.lookMountFeet = getNumber<uint8_t>(L, 13, outfit.lookMountFeet); - outfit.lookMountLegs = getNumber<uint8_t>(L, 12, outfit.lookMountLegs); - outfit.lookMountBody = getNumber<uint8_t>(L, 11, outfit.lookMountBody); - outfit.lookMountHead = getNumber<uint8_t>(L, 10, outfit.lookMountHead); - outfit.lookMount = getNumber<uint16_t>(L, 9, outfit.lookMount); - outfit.lookAddons = getNumber<uint8_t>(L, 8, outfit.lookAddons); - outfit.lookFeet = getNumber<uint8_t>(L, 7); - outfit.lookLegs = getNumber<uint8_t>(L, 6); - outfit.lookBody = getNumber<uint8_t>(L, 5); - outfit.lookHead = getNumber<uint8_t>(L, 4); - outfit.lookType = getNumber<uint16_t>(L, 3); - outfit.lookTypeEx = getNumber<uint16_t>(L, 2); - } - - std::shared_ptr<ConditionOutfit> condition = getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionOutfit>(); + outfit.lookFamiliarsType = Lua::getNumber<uint16_t>(L, 14, outfit.lookFamiliarsType); + outfit.lookMountFeet = Lua::getNumber<uint8_t>(L, 13, outfit.lookMountFeet); + outfit.lookMountLegs = Lua::getNumber<uint8_t>(L, 12, outfit.lookMountLegs); + outfit.lookMountBody = Lua::getNumber<uint8_t>(L, 11, outfit.lookMountBody); + outfit.lookMountHead = Lua::getNumber<uint8_t>(L, 10, outfit.lookMountHead); + outfit.lookMount = Lua::getNumber<uint16_t>(L, 9, outfit.lookMount); + outfit.lookAddons = Lua::getNumber<uint8_t>(L, 8, outfit.lookAddons); + outfit.lookFeet = Lua::getNumber<uint8_t>(L, 7); + outfit.lookLegs = Lua::getNumber<uint8_t>(L, 6); + outfit.lookBody = Lua::getNumber<uint8_t>(L, 5); + outfit.lookHead = Lua::getNumber<uint8_t>(L, 4); + outfit.lookType = Lua::getNumber<uint16_t>(L, 3); + outfit.lookTypeEx = Lua::getNumber<uint16_t>(L, 2); + } + + const std::shared_ptr<ConditionOutfit> &condition = Lua::getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionOutfit>(); if (condition) { condition->setOutfit(outfit); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -210,12 +237,12 @@ int ConditionFunctions::luaConditionSetOutfit(lua_State* L) { int ConditionFunctions::luaConditionAddDamage(lua_State* L) { // condition:addDamage(rounds, time, value) - int32_t value = getNumber<int32_t>(L, 4); - int32_t time = getNumber<int32_t>(L, 3); - int32_t rounds = getNumber<int32_t>(L, 2); - std::shared_ptr<ConditionDamage> condition = getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionDamage>(); + const int32_t value = Lua::getNumber<int32_t>(L, 4); + const int32_t time = Lua::getNumber<int32_t>(L, 3); + const int32_t rounds = Lua::getNumber<int32_t>(L, 2); + const std::shared_ptr<ConditionDamage> &condition = Lua::getUserdataShared<Condition>(L, 1)->dynamic_self_cast<ConditionDamage>(); if (condition) { - pushBoolean(L, condition->addDamage(rounds, time, value)); + Lua::pushBoolean(L, condition->addDamage(rounds, time, value)); } else { lua_pushnil(L); } diff --git a/src/lua/functions/creatures/combat/condition_functions.hpp b/src/lua/functions/creatures/combat/condition_functions.hpp index 938c5170542..e8a3e834207 100644 --- a/src/lua/functions/creatures/combat/condition_functions.hpp +++ b/src/lua/functions/creatures/combat/condition_functions.hpp @@ -9,33 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ConditionFunctions final : LuaScriptInterface { +class ConditionFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Condition", "", ConditionFunctions::luaConditionCreate); - registerMetaMethod(L, "Condition", "__eq", ConditionFunctions::luaUserdataCompare); - registerMetaMethod(L, "Condition", "__gc", ConditionFunctions::luaConditionDelete); - registerMethod(L, "Condition", "delete", ConditionFunctions::luaConditionDelete); - - registerMethod(L, "Condition", "getId", ConditionFunctions::luaConditionGetId); - registerMethod(L, "Condition", "getSubId", ConditionFunctions::luaConditionGetSubId); - registerMethod(L, "Condition", "getType", ConditionFunctions::luaConditionGetType); - registerMethod(L, "Condition", "getIcons", ConditionFunctions::luaConditionGetIcons); - registerMethod(L, "Condition", "getEndTime", ConditionFunctions::luaConditionGetEndTime); - - registerMethod(L, "Condition", "clone", ConditionFunctions::luaConditionClone); - - registerMethod(L, "Condition", "getTicks", ConditionFunctions::luaConditionGetTicks); - registerMethod(L, "Condition", "setTicks", ConditionFunctions::luaConditionSetTicks); - - registerMethod(L, "Condition", "setParameter", ConditionFunctions::luaConditionSetParameter); - registerMethod(L, "Condition", "setFormula", ConditionFunctions::luaConditionSetFormula); - registerMethod(L, "Condition", "setOutfit", ConditionFunctions::luaConditionSetOutfit); - - registerMethod(L, "Condition", "addDamage", ConditionFunctions::luaConditionAddDamage); - } + static void init(lua_State* L); private: static int luaConditionCreate(lua_State* L); diff --git a/src/lua/functions/creatures/combat/spell_functions.cpp b/src/lua/functions/creatures/combat/spell_functions.cpp index 18fdce42fdb..0d2d4a955ef 100644 --- a/src/lua/functions/creatures/combat/spell_functions.cpp +++ b/src/lua/functions/creatures/combat/spell_functions.cpp @@ -7,9 +7,61 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/combat/spell_functions.hpp" + #include "creatures/combat/spells.hpp" #include "creatures/players/vocations/vocation.hpp" -#include "lua/functions/creatures/combat/spell_functions.hpp" +#include "items/item.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void SpellFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Spell", "", SpellFunctions::luaSpellCreate); + Lua::registerMetaMethod(L, "Spell", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Spell", "onCastSpell", SpellFunctions::luaSpellOnCastSpell); + Lua::registerMethod(L, "Spell", "register", SpellFunctions::luaSpellRegister); + Lua::registerMethod(L, "Spell", "name", SpellFunctions::luaSpellName); + Lua::registerMethod(L, "Spell", "id", SpellFunctions::luaSpellId); + Lua::registerMethod(L, "Spell", "group", SpellFunctions::luaSpellGroup); + Lua::registerMethod(L, "Spell", "cooldown", SpellFunctions::luaSpellCooldown); + Lua::registerMethod(L, "Spell", "groupCooldown", SpellFunctions::luaSpellGroupCooldown); + Lua::registerMethod(L, "Spell", "level", SpellFunctions::luaSpellLevel); + Lua::registerMethod(L, "Spell", "magicLevel", SpellFunctions::luaSpellMagicLevel); + Lua::registerMethod(L, "Spell", "mana", SpellFunctions::luaSpellMana); + Lua::registerMethod(L, "Spell", "manaPercent", SpellFunctions::luaSpellManaPercent); + Lua::registerMethod(L, "Spell", "soul", SpellFunctions::luaSpellSoul); + Lua::registerMethod(L, "Spell", "range", SpellFunctions::luaSpellRange); + Lua::registerMethod(L, "Spell", "isPremium", SpellFunctions::luaSpellPremium); + Lua::registerMethod(L, "Spell", "isEnabled", SpellFunctions::luaSpellEnabled); + Lua::registerMethod(L, "Spell", "needTarget", SpellFunctions::luaSpellNeedTarget); + Lua::registerMethod(L, "Spell", "needWeapon", SpellFunctions::luaSpellNeedWeapon); + Lua::registerMethod(L, "Spell", "needLearn", SpellFunctions::luaSpellNeedLearn); + Lua::registerMethod(L, "Spell", "allowOnSelf", SpellFunctions::luaSpellAllowOnSelf); + Lua::registerMethod(L, "Spell", "setPzLocked", SpellFunctions::luaSpellPzLocked); + Lua::registerMethod(L, "Spell", "isSelfTarget", SpellFunctions::luaSpellSelfTarget); + Lua::registerMethod(L, "Spell", "isBlocking", SpellFunctions::luaSpellBlocking); + Lua::registerMethod(L, "Spell", "isAggressive", SpellFunctions::luaSpellAggressive); + Lua::registerMethod(L, "Spell", "vocation", SpellFunctions::luaSpellVocation); + + Lua::registerMethod(L, "Spell", "castSound", SpellFunctions::luaSpellCastSound); + Lua::registerMethod(L, "Spell", "impactSound", SpellFunctions::luaSpellImpactSound); + + // Only for InstantSpell. + Lua::registerMethod(L, "Spell", "words", SpellFunctions::luaSpellWords); + Lua::registerMethod(L, "Spell", "needDirection", SpellFunctions::luaSpellNeedDirection); + Lua::registerMethod(L, "Spell", "hasParams", SpellFunctions::luaSpellHasParams); + Lua::registerMethod(L, "Spell", "hasPlayerNameParam", SpellFunctions::luaSpellHasPlayerNameParam); + Lua::registerMethod(L, "Spell", "needCasterTargetOrDirection", SpellFunctions::luaSpellNeedCasterTargetOrDirection); + Lua::registerMethod(L, "Spell", "isBlockingWalls", SpellFunctions::luaSpellIsBlockingWalls); + + // Only for RuneSpells. + Lua::registerMethod(L, "Spell", "runeId", SpellFunctions::luaSpellRuneId); + Lua::registerMethod(L, "Spell", "charges", SpellFunctions::luaSpellCharges); + Lua::registerMethod(L, "Spell", "allowFarUse", SpellFunctions::luaSpellAllowFarUse); + Lua::registerMethod(L, "Spell", "blockWalls", SpellFunctions::luaSpellBlockWalls); + Lua::registerMethod(L, "Spell", "checkFloor", SpellFunctions::luaSpellCheckFloor); +} int SpellFunctions::luaSpellCreate(lua_State* L) { // Spell(words, name or id) to get an existing spell @@ -23,39 +75,39 @@ int SpellFunctions::luaSpellCreate(lua_State* L) { SpellType_t spellType = SPELL_UNDEFINED; - if (isNumber(L, 2)) { - uint16_t id = getNumber<uint16_t>(L, 2); - std::shared_ptr<RuneSpell> rune = g_spells().getRuneSpell(id); + if (Lua::isNumber(L, 2)) { + uint16_t id = Lua::getNumber<uint16_t>(L, 2); + const auto &rune = g_spells().getRuneSpell(id); if (rune) { - pushUserdata<Spell>(L, rune); - setMetatable(L, -1, "Spell"); + Lua::pushUserdata<Spell>(L, rune); + Lua::setMetatable(L, -1, "Spell"); return 1; } spellType = static_cast<SpellType_t>(id); - } else if (isString(L, 2)) { - std::string arg = getString(L, 2); - std::shared_ptr<InstantSpell> instant = g_spells().getInstantSpellByName(arg); + } else if (Lua::isString(L, 2)) { + const std::string arg = Lua::getString(L, 2); + auto instant = g_spells().getInstantSpellByName(arg); if (instant) { - pushUserdata<Spell>(L, instant); - setMetatable(L, -1, "Spell"); + Lua::pushUserdata<Spell>(L, instant); + Lua::setMetatable(L, -1, "Spell"); return 1; } instant = g_spells().getInstantSpell(arg); if (instant) { - pushUserdata<Spell>(L, instant); - setMetatable(L, -1, "Spell"); + Lua::pushUserdata<Spell>(L, instant); + Lua::setMetatable(L, -1, "Spell"); return 1; } - std::shared_ptr<RuneSpell> rune = g_spells().getRuneSpellByName(arg); + const auto &rune = g_spells().getRuneSpellByName(arg); if (rune) { - pushUserdata<Spell>(L, rune); - setMetatable(L, -1, "Spell"); + Lua::pushUserdata<Spell>(L, rune); + Lua::setMetatable(L, -1, "Spell"); return 1; } - std::string tmp = asLowerCaseString(arg); + const std::string tmp = asLowerCaseString(arg); if (tmp == "instant") { spellType = SPELL_INSTANT; } else if (tmp == "rune") { @@ -64,15 +116,15 @@ int SpellFunctions::luaSpellCreate(lua_State* L) { } if (spellType == SPELL_INSTANT) { - auto spell = std::make_shared<InstantSpell>(getScriptEnv()->getScriptInterface()); - pushUserdata<Spell>(L, spell); - setMetatable(L, -1, "Spell"); + const auto &spell = std::make_shared<InstantSpell>(); + Lua::pushUserdata<Spell>(L, spell); + Lua::setMetatable(L, -1, "Spell"); spell->spellType = SPELL_INSTANT; return 1; } else if (spellType == SPELL_RUNE) { - auto runeSpell = std::make_shared<RuneSpell>(getScriptEnv()->getScriptInterface()); - pushUserdata<Spell>(L, runeSpell); - setMetatable(L, -1, "Spell"); + const auto &runeSpell = std::make_shared<RuneSpell>(); + Lua::pushUserdata<Spell>(L, runeSpell); + Lua::setMetatable(L, -1, "Spell"); runeSpell->spellType = SPELL_RUNE; return 1; } @@ -83,26 +135,22 @@ int SpellFunctions::luaSpellCreate(lua_State* L) { int SpellFunctions::luaSpellOnCastSpell(lua_State* L) { // spell:onCastSpell(callback) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (spell->spellType == SPELL_INSTANT) { - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto instant = std::static_pointer_cast<InstantSpell>(spellBase); - if (!instant->loadCallback()) { - pushBoolean(L, false); + const auto &instant = std::static_pointer_cast<InstantSpell>(spell); + if (!instant->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - instant->setLoadedCallback(true); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else if (spell->spellType == SPELL_RUNE) { - std::shared_ptr<Spell> spellBase = getUserdataShared<Spell>(L, 1); - std::shared_ptr<RuneSpell> rune = std::static_pointer_cast<RuneSpell>(spellBase); - if (!rune->loadCallback()) { - pushBoolean(L, false); + const auto &rune = std::static_pointer_cast<RuneSpell>(spell); + if (!rune->loadRuneSpellScriptId()) { + Lua::pushBoolean(L, false); return 1; } - rune->setLoadedCallback(true); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -112,24 +160,24 @@ int SpellFunctions::luaSpellOnCastSpell(lua_State* L) { int SpellFunctions::luaSpellRegister(lua_State* L) { // spell:register() - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (!spell) { - reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (spell->spellType == SPELL_INSTANT) { - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto instant = std::static_pointer_cast<InstantSpell>(spellBase); - if (!instant->isLoadedCallback()) { - pushBoolean(L, false); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &instant = std::static_pointer_cast<InstantSpell>(spellBase); + if (!instant->isLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_spells().registerInstantLuaEvent(instant)); + Lua::pushBoolean(L, g_spells().registerInstantLuaEvent(instant)); } else if (spell->spellType == SPELL_RUNE) { - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto rune = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &rune = std::static_pointer_cast<RuneSpell>(spellBase); if (rune->getMagicLevel() != 0 || rune->getLevel() != 0) { // Change information in the ItemType to get accurate description ItemType &iType = Item::items.getItemType(rune->getRuneItemId()); @@ -141,11 +189,11 @@ int SpellFunctions::luaSpellRegister(lua_State* L) { iType.runeLevel = rune->getLevel(); iType.charges = rune->getCharges(); } - if (!rune->isLoadedCallback()) { - pushBoolean(L, false); + if (!rune->isRuneSpellLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_spells().registerRuneLuaEvent(rune)); + Lua::pushBoolean(L, g_spells().registerRuneLuaEvent(rune)); } return 1; } @@ -153,13 +201,13 @@ int SpellFunctions::luaSpellRegister(lua_State* L) { int SpellFunctions::luaSpellName(lua_State* L) { // spell:name(name) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushString(L, spell->getName()); + Lua::pushString(L, spell->getName()); } else { - spell->setName(getString(L, 2)); - pushBoolean(L, true); + spell->setName(Lua::getString(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -169,18 +217,18 @@ int SpellFunctions::luaSpellName(lua_State* L) { int SpellFunctions::luaSpellId(lua_State* L) { // spell:id(id) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (spell->spellType != SPELL_INSTANT && spell->spellType != SPELL_RUNE) { - reportErrorFunc("The method: 'spell:id(id)' is only for use of instant spells and rune spells"); - pushBoolean(L, false); + Lua::reportErrorFunc("The method: 'spell:id(id)' is only for use of instant spells and rune spells"); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getSpellId()); } else { - spell->setSpellId(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + spell->setSpellId(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -190,70 +238,70 @@ int SpellFunctions::luaSpellId(lua_State* L) { int SpellFunctions::luaSpellGroup(lua_State* L) { // spell:group(primaryGroup[, secondaryGroup]) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getGroup()); lua_pushnumber(L, spell->getSecondaryGroup()); return 2; } else if (lua_gettop(L) == 2) { - SpellGroup_t group = getNumber<SpellGroup_t>(L, 2); + auto group = Lua::getNumber<SpellGroup_t>(L, 2); if (group) { spell->setGroup(group); - pushBoolean(L, true); - } else if (isString(L, 2)) { - group = stringToSpellGroup(getString(L, 2)); + Lua::pushBoolean(L, true); + } else if (Lua::isString(L, 2)) { + group = stringToSpellGroup(Lua::getString(L, 2)); if (group != SPELLGROUP_NONE) { spell->setGroup(group); } else { g_logger().warn("[SpellFunctions::luaSpellGroup] - " "Unknown group: {}", - getString(L, 2)); - pushBoolean(L, false); + Lua::getString(L, 2)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { g_logger().warn("[SpellFunctions::luaSpellGroup] - " "Unknown group: {}", - getString(L, 2)); - pushBoolean(L, false); + Lua::getString(L, 2)); + Lua::pushBoolean(L, false); return 1; } } else { - SpellGroup_t primaryGroup = getNumber<SpellGroup_t>(L, 2); - SpellGroup_t secondaryGroup = getNumber<SpellGroup_t>(L, 2); + auto primaryGroup = Lua::getNumber<SpellGroup_t>(L, 2); + auto secondaryGroup = Lua::getNumber<SpellGroup_t>(L, 2); if (primaryGroup && secondaryGroup) { spell->setGroup(primaryGroup); spell->setSecondaryGroup(secondaryGroup); - pushBoolean(L, true); - } else if (isString(L, 2) && isString(L, 3)) { - primaryGroup = stringToSpellGroup(getString(L, 2)); + Lua::pushBoolean(L, true); + } else if (Lua::isString(L, 2) && Lua::isString(L, 3)) { + primaryGroup = stringToSpellGroup(Lua::getString(L, 2)); if (primaryGroup != SPELLGROUP_NONE) { spell->setGroup(primaryGroup); } else { g_logger().warn("[SpellFunctions::luaSpellGroup] - " "Unknown primaryGroup: {}", - getString(L, 2)); - pushBoolean(L, false); + Lua::getString(L, 2)); + Lua::pushBoolean(L, false); return 1; } - secondaryGroup = stringToSpellGroup(getString(L, 3)); + secondaryGroup = stringToSpellGroup(Lua::getString(L, 3)); if (secondaryGroup != SPELLGROUP_NONE) { spell->setSecondaryGroup(secondaryGroup); } else { g_logger().warn("[SpellFunctions::luaSpellGroup] - " "Unknown secondaryGroup: {}", - getString(L, 3)); - pushBoolean(L, false); + Lua::getString(L, 3)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { g_logger().warn("[SpellFunctions::luaSpellGroup] - " "Unknown primaryGroup: {} or secondaryGroup: {}", - getString(L, 2), getString(L, 3)); - pushBoolean(L, false); + Lua::getString(L, 2), Lua::getString(L, 3)); + Lua::pushBoolean(L, false); return 1; } } @@ -265,13 +313,13 @@ int SpellFunctions::luaSpellGroup(lua_State* L) { int SpellFunctions::luaSpellCastSound(lua_State* L) { // get: spell:castSound() set: spell:castSound(effect) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<uint16_t>(spell->soundCastEffect)); } else { - spell->soundCastEffect = static_cast<SoundEffect_t>(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + spell->soundCastEffect = static_cast<SoundEffect_t>(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -281,13 +329,13 @@ int SpellFunctions::luaSpellCastSound(lua_State* L) { int SpellFunctions::luaSpellImpactSound(lua_State* L) { // get: spell:impactSound() set: spell:impactSound(effect) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<uint16_t>(spell->soundImpactEffect)); } else { - spell->soundImpactEffect = static_cast<SoundEffect_t>(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + spell->soundImpactEffect = static_cast<SoundEffect_t>(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -297,13 +345,13 @@ int SpellFunctions::luaSpellImpactSound(lua_State* L) { int SpellFunctions::luaSpellCooldown(lua_State* L) { // spell:cooldown(cooldown) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getCooldown()); } else { - spell->setCooldown(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setCooldown(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -313,19 +361,19 @@ int SpellFunctions::luaSpellCooldown(lua_State* L) { int SpellFunctions::luaSpellGroupCooldown(lua_State* L) { // spell:groupCooldown(primaryGroupCd[, secondaryGroupCd]) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getGroupCooldown()); lua_pushnumber(L, spell->getSecondaryCooldown()); return 2; } else if (lua_gettop(L) == 2) { - spell->setGroupCooldown(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setGroupCooldown(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { - spell->setGroupCooldown(getNumber<uint32_t>(L, 2)); - spell->setSecondaryCooldown(getNumber<uint32_t>(L, 3)); - pushBoolean(L, true); + spell->setGroupCooldown(Lua::getNumber<uint32_t>(L, 2)); + spell->setSecondaryCooldown(Lua::getNumber<uint32_t>(L, 3)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -335,13 +383,13 @@ int SpellFunctions::luaSpellGroupCooldown(lua_State* L) { int SpellFunctions::luaSpellLevel(lua_State* L) { // spell:level(lvl) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getLevel()); } else { - spell->setLevel(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setLevel(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -351,13 +399,13 @@ int SpellFunctions::luaSpellLevel(lua_State* L) { int SpellFunctions::luaSpellMagicLevel(lua_State* L) { // spell:magicLevel(lvl) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getMagicLevel()); } else { - spell->setMagicLevel(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setMagicLevel(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -367,13 +415,13 @@ int SpellFunctions::luaSpellMagicLevel(lua_State* L) { int SpellFunctions::luaSpellMana(lua_State* L) { // spell:mana(mana) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getMana()); } else { - spell->setMana(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setMana(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -383,13 +431,13 @@ int SpellFunctions::luaSpellMana(lua_State* L) { int SpellFunctions::luaSpellManaPercent(lua_State* L) { // spell:manaPercent(percent) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getManaPercent()); } else { - spell->setManaPercent(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setManaPercent(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -399,13 +447,13 @@ int SpellFunctions::luaSpellManaPercent(lua_State* L) { int SpellFunctions::luaSpellSoul(lua_State* L) { // spell:soul(soul) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getSoulCost()); } else { - spell->setSoulCost(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setSoulCost(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -415,13 +463,13 @@ int SpellFunctions::luaSpellSoul(lua_State* L) { int SpellFunctions::luaSpellRange(lua_State* L) { // spell:range(range) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getRange()); } else { - spell->setRange(getNumber<int32_t>(L, 2)); - pushBoolean(L, true); + spell->setRange(Lua::getNumber<int32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -431,13 +479,13 @@ int SpellFunctions::luaSpellRange(lua_State* L) { int SpellFunctions::luaSpellPremium(lua_State* L) { // spell:isPremium(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->isPremium()); + Lua::pushBoolean(L, spell->isPremium()); } else { - spell->setPremium(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setPremium(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -447,13 +495,13 @@ int SpellFunctions::luaSpellPremium(lua_State* L) { int SpellFunctions::luaSpellEnabled(lua_State* L) { // spell:isEnabled(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->isEnabled()); + Lua::pushBoolean(L, spell->isEnabled()); } else { - spell->setEnabled(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setEnabled(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -463,13 +511,13 @@ int SpellFunctions::luaSpellEnabled(lua_State* L) { int SpellFunctions::luaSpellNeedTarget(lua_State* L) { // spell:needTarget(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getNeedTarget()); + Lua::pushBoolean(L, spell->getNeedTarget()); } else { - spell->setNeedTarget(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setNeedTarget(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -479,13 +527,13 @@ int SpellFunctions::luaSpellNeedTarget(lua_State* L) { int SpellFunctions::luaSpellNeedWeapon(lua_State* L) { // spell:needWeapon(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getNeedWeapon()); + Lua::pushBoolean(L, spell->getNeedWeapon()); } else { - spell->setNeedWeapon(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setNeedWeapon(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -495,13 +543,13 @@ int SpellFunctions::luaSpellNeedWeapon(lua_State* L) { int SpellFunctions::luaSpellNeedLearn(lua_State* L) { // spell:needLearn(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getNeedLearn()); + Lua::pushBoolean(L, spell->getNeedLearn()); } else { - spell->setNeedLearn(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setNeedLearn(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -511,12 +559,12 @@ int SpellFunctions::luaSpellNeedLearn(lua_State* L) { int SpellFunctions::luaSpellSelfTarget(lua_State* L) { // spell:isSelfTarget(bool) - if (const auto spell = getUserdataShared<Spell>(L, 1)) { + if (const auto &spell = Lua::getUserdataShared<Spell>(L, 1)) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getSelfTarget()); + Lua::pushBoolean(L, spell->getSelfTarget()); } else { - spell->setSelfTarget(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setSelfTarget(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -526,15 +574,15 @@ int SpellFunctions::luaSpellSelfTarget(lua_State* L) { int SpellFunctions::luaSpellBlocking(lua_State* L) { // spell:isBlocking(blockingSolid, blockingCreature) - if (const auto spell = getUserdataShared<Spell>(L, 1)) { + if (const auto &spell = Lua::getUserdataShared<Spell>(L, 1)) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getBlockingSolid()); - pushBoolean(L, spell->getBlockingCreature()); + Lua::pushBoolean(L, spell->getBlockingSolid()); + Lua::pushBoolean(L, spell->getBlockingCreature()); return 2; } else { - spell->setBlockingSolid(getBoolean(L, 2)); - spell->setBlockingCreature(getBoolean(L, 3)); - pushBoolean(L, true); + spell->setBlockingSolid(Lua::getBoolean(L, 2)); + spell->setBlockingCreature(Lua::getBoolean(L, 3)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -544,13 +592,13 @@ int SpellFunctions::luaSpellBlocking(lua_State* L) { int SpellFunctions::luaSpellAggressive(lua_State* L) { // spell:isAggressive(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getAggressive()); + Lua::pushBoolean(L, spell->getAggressive()); } else { - spell->setAggressive(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setAggressive(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -560,13 +608,13 @@ int SpellFunctions::luaSpellAggressive(lua_State* L) { int SpellFunctions::luaSpellAllowOnSelf(lua_State* L) { // spell:allowOnSelf(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getAllowOnSelf()); + Lua::pushBoolean(L, spell->getAllowOnSelf()); } else { - spell->setAllowOnSelf(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setAllowOnSelf(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -576,13 +624,13 @@ int SpellFunctions::luaSpellAllowOnSelf(lua_State* L) { int SpellFunctions::luaSpellPzLocked(lua_State* L) { // spell:isPzLocked(bool) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getLockedPZ()); + Lua::pushBoolean(L, spell->getLockedPZ()); } else { - spell->setLockedPZ(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setLockedPZ(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -592,26 +640,26 @@ int SpellFunctions::luaSpellPzLocked(lua_State* L) { int SpellFunctions::luaSpellVocation(lua_State* L) { // spell:vocation(vocation) - const auto spell = getUserdataShared<Spell>(L, 1); + const auto &spell = Lua::getUserdataShared<Spell>(L, 1); if (spell) { if (lua_gettop(L) == 1) { lua_createtable(L, 0, 0); auto it = 0; - for (auto voc : spell->getVocMap()) { + for (const auto &voc : spell->getVocMap()) { ++it; std::string s = std::to_string(it); const char* pchar = s.c_str(); std::string name = g_vocations().getVocation(voc.first)->getVocName(); - setField(L, pchar, name); + Lua::setField(L, pchar, name); } - setMetatable(L, -1, "Spell"); + Lua::setMetatable(L, -1, "Spell"); } else { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc for (int i = 0; i < parameters; ++i) { - if (getString(L, 2 + i).find(";") != std::string::npos) { - std::vector<std::string> vocList = explodeString(getString(L, 2 + i), ";"); - int32_t vocationId = g_vocations().getVocationId(vocList[0]); - if (vocList.size() > 0) { + if (Lua::getString(L, 2 + i).find(';') != std::string::npos) { + std::vector<std::string> vocList = explodeString(Lua::getString(L, 2 + i), ";"); + const int32_t vocationId = g_vocations().getVocationId(vocList[0]); + if (!vocList.empty()) { if (vocList[1] == "true") { spell->addVocMap(vocationId, true); } else { @@ -619,11 +667,11 @@ int SpellFunctions::luaSpellVocation(lua_State* L) { } } } else { - int32_t vocationId = g_vocations().getVocationId(getString(L, 2 + i)); + const int32_t vocationId = g_vocations().getVocationId(Lua::getString(L, 2 + i)); spell->addVocMap(vocationId, false); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -634,8 +682,8 @@ int SpellFunctions::luaSpellVocation(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellWords(lua_State* L) { // spell:words(words[, separator = ""]) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -644,17 +692,17 @@ int SpellFunctions::luaSpellWords(lua_State* L) { } if (lua_gettop(L) == 1) { - pushString(L, spell->getWords()); - pushString(L, spell->getSeparator()); + Lua::pushString(L, spell->getWords()); + Lua::pushString(L, spell->getSeparator()); return 2; } else { - std::string sep = ""; + std::string sep; if (lua_gettop(L) == 3) { - sep = getString(L, 3); + sep = Lua::getString(L, 3); } - spell->setWords(getString(L, 2)); + spell->setWords(Lua::getString(L, 2)); spell->setSeparator(sep); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -665,8 +713,8 @@ int SpellFunctions::luaSpellWords(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellNeedDirection(lua_State* L) { // spell:needDirection(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -675,10 +723,10 @@ int SpellFunctions::luaSpellNeedDirection(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getNeedDirection()); + Lua::pushBoolean(L, spell->getNeedDirection()); } else { - spell->setNeedDirection(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setNeedDirection(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -689,8 +737,8 @@ int SpellFunctions::luaSpellNeedDirection(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellHasParams(lua_State* L) { // spell:hasParams(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -699,10 +747,10 @@ int SpellFunctions::luaSpellHasParams(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getHasParam()); + Lua::pushBoolean(L, spell->getHasParam()); } else { - spell->setHasParam(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setHasParam(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -713,8 +761,8 @@ int SpellFunctions::luaSpellHasParams(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellHasPlayerNameParam(lua_State* L) { // spell:hasPlayerNameParam(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -723,10 +771,10 @@ int SpellFunctions::luaSpellHasPlayerNameParam(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getHasPlayerNameParam()); + Lua::pushBoolean(L, spell->getHasPlayerNameParam()); } else { - spell->setHasPlayerNameParam(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setHasPlayerNameParam(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -737,8 +785,8 @@ int SpellFunctions::luaSpellHasPlayerNameParam(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellNeedCasterTargetOrDirection(lua_State* L) { // spell:needCasterTargetOrDirection(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -747,10 +795,10 @@ int SpellFunctions::luaSpellNeedCasterTargetOrDirection(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getNeedCasterTargetOrDirection()); + Lua::pushBoolean(L, spell->getNeedCasterTargetOrDirection()); } else { - spell->setNeedCasterTargetOrDirection(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setNeedCasterTargetOrDirection(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -761,8 +809,8 @@ int SpellFunctions::luaSpellNeedCasterTargetOrDirection(lua_State* L) { // only for InstantSpells int SpellFunctions::luaSpellIsBlockingWalls(lua_State* L) { // spell:blockWalls(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<InstantSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<InstantSpell>(spellBase); if (spell) { // if spell != SPELL_INSTANT, it means that this actually is no InstantSpell, so we return nil if (spell->spellType != SPELL_INSTANT) { @@ -771,10 +819,10 @@ int SpellFunctions::luaSpellIsBlockingWalls(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getBlockWalls()); + Lua::pushBoolean(L, spell->getBlockWalls()); } else { - spell->setBlockWalls(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setBlockWalls(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -785,8 +833,8 @@ int SpellFunctions::luaSpellIsBlockingWalls(lua_State* L) { // only for RuneSpells int SpellFunctions::luaSpellRuneId(lua_State* L) { // spell:runeId(id) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<RuneSpell>(spellBase); if (spell) { // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so we return nil if (spell->spellType != SPELL_RUNE) { @@ -797,8 +845,8 @@ int SpellFunctions::luaSpellRuneId(lua_State* L) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getRuneItemId()); } else { - spell->setRuneItemId(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + spell->setRuneItemId(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -809,8 +857,8 @@ int SpellFunctions::luaSpellRuneId(lua_State* L) { // only for RuneSpells int SpellFunctions::luaSpellCharges(lua_State* L) { // spell:charges(charges) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<RuneSpell>(spellBase); if (spell) { // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so we return nil if (spell->spellType != SPELL_RUNE) { @@ -821,8 +869,8 @@ int SpellFunctions::luaSpellCharges(lua_State* L) { if (lua_gettop(L) == 1) { lua_pushnumber(L, spell->getCharges()); } else { - spell->setCharges(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + spell->setCharges(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -833,8 +881,8 @@ int SpellFunctions::luaSpellCharges(lua_State* L) { // only for RuneSpells int SpellFunctions::luaSpellAllowFarUse(lua_State* L) { // spell:allowFarUse(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<RuneSpell>(spellBase); if (spell) { // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so we return nil if (spell->spellType != SPELL_RUNE) { @@ -843,10 +891,10 @@ int SpellFunctions::luaSpellAllowFarUse(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getAllowFarUse()); + Lua::pushBoolean(L, spell->getAllowFarUse()); } else { - spell->setAllowFarUse(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setAllowFarUse(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -857,8 +905,8 @@ int SpellFunctions::luaSpellAllowFarUse(lua_State* L) { // only for RuneSpells int SpellFunctions::luaSpellBlockWalls(lua_State* L) { // spell:blockWalls(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<RuneSpell>(spellBase); if (spell) { // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so we return nil if (spell->spellType != SPELL_RUNE) { @@ -867,10 +915,10 @@ int SpellFunctions::luaSpellBlockWalls(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getCheckLineOfSight()); + Lua::pushBoolean(L, spell->getCheckLineOfSight()); } else { - spell->setCheckLineOfSight(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setCheckLineOfSight(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -881,8 +929,8 @@ int SpellFunctions::luaSpellBlockWalls(lua_State* L) { // only for RuneSpells int SpellFunctions::luaSpellCheckFloor(lua_State* L) { // spell:checkFloor(bool) - const auto spellBase = getUserdataShared<Spell>(L, 1); - const auto spell = std::static_pointer_cast<RuneSpell>(spellBase); + const auto &spellBase = Lua::getUserdataShared<Spell>(L, 1); + const auto &spell = std::static_pointer_cast<RuneSpell>(spellBase); if (spell) { // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so we return nil if (spell->spellType != SPELL_RUNE) { @@ -891,10 +939,10 @@ int SpellFunctions::luaSpellCheckFloor(lua_State* L) { } if (lua_gettop(L) == 1) { - pushBoolean(L, spell->getCheckFloor()); + Lua::pushBoolean(L, spell->getCheckFloor()); } else { - spell->setCheckFloor(getBoolean(L, 2)); - pushBoolean(L, true); + spell->setCheckFloor(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); diff --git a/src/lua/functions/creatures/combat/spell_functions.hpp b/src/lua/functions/creatures/combat/spell_functions.hpp index ac28d9e5232..684b8af8ba2 100644 --- a/src/lua/functions/creatures/combat/spell_functions.hpp +++ b/src/lua/functions/creatures/combat/spell_functions.hpp @@ -9,57 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class SpellFunctions final : LuaScriptInterface { +class SpellFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Spell", "", SpellFunctions::luaSpellCreate); - registerMetaMethod(L, "Spell", "__eq", SpellFunctions::luaUserdataCompare); - - registerMethod(L, "Spell", "onCastSpell", SpellFunctions::luaSpellOnCastSpell); - registerMethod(L, "Spell", "register", SpellFunctions::luaSpellRegister); - registerMethod(L, "Spell", "name", SpellFunctions::luaSpellName); - registerMethod(L, "Spell", "id", SpellFunctions::luaSpellId); - registerMethod(L, "Spell", "group", SpellFunctions::luaSpellGroup); - registerMethod(L, "Spell", "cooldown", SpellFunctions::luaSpellCooldown); - registerMethod(L, "Spell", "groupCooldown", SpellFunctions::luaSpellGroupCooldown); - registerMethod(L, "Spell", "level", SpellFunctions::luaSpellLevel); - registerMethod(L, "Spell", "magicLevel", SpellFunctions::luaSpellMagicLevel); - registerMethod(L, "Spell", "mana", SpellFunctions::luaSpellMana); - registerMethod(L, "Spell", "manaPercent", SpellFunctions::luaSpellManaPercent); - registerMethod(L, "Spell", "soul", SpellFunctions::luaSpellSoul); - registerMethod(L, "Spell", "range", SpellFunctions::luaSpellRange); - registerMethod(L, "Spell", "isPremium", SpellFunctions::luaSpellPremium); - registerMethod(L, "Spell", "isEnabled", SpellFunctions::luaSpellEnabled); - registerMethod(L, "Spell", "needTarget", SpellFunctions::luaSpellNeedTarget); - registerMethod(L, "Spell", "needWeapon", SpellFunctions::luaSpellNeedWeapon); - registerMethod(L, "Spell", "needLearn", SpellFunctions::luaSpellNeedLearn); - registerMethod(L, "Spell", "allowOnSelf", SpellFunctions::luaSpellAllowOnSelf); - registerMethod(L, "Spell", "setPzLocked", SpellFunctions::luaSpellPzLocked); - registerMethod(L, "Spell", "isSelfTarget", SpellFunctions::luaSpellSelfTarget); - registerMethod(L, "Spell", "isBlocking", SpellFunctions::luaSpellBlocking); - registerMethod(L, "Spell", "isAggressive", SpellFunctions::luaSpellAggressive); - registerMethod(L, "Spell", "vocation", SpellFunctions::luaSpellVocation); - - registerMethod(L, "Spell", "castSound", SpellFunctions::luaSpellCastSound); - registerMethod(L, "Spell", "impactSound", SpellFunctions::luaSpellImpactSound); - - // Only for InstantSpell. - registerMethod(L, "Spell", "words", SpellFunctions::luaSpellWords); - registerMethod(L, "Spell", "needDirection", SpellFunctions::luaSpellNeedDirection); - registerMethod(L, "Spell", "hasParams", SpellFunctions::luaSpellHasParams); - registerMethod(L, "Spell", "hasPlayerNameParam", SpellFunctions::luaSpellHasPlayerNameParam); - registerMethod(L, "Spell", "needCasterTargetOrDirection", SpellFunctions::luaSpellNeedCasterTargetOrDirection); - registerMethod(L, "Spell", "isBlockingWalls", SpellFunctions::luaSpellIsBlockingWalls); - - // Only for RuneSpells. - registerMethod(L, "Spell", "runeId", SpellFunctions::luaSpellRuneId); - registerMethod(L, "Spell", "charges", SpellFunctions::luaSpellCharges); - registerMethod(L, "Spell", "allowFarUse", SpellFunctions::luaSpellAllowFarUse); - registerMethod(L, "Spell", "blockWalls", SpellFunctions::luaSpellBlockWalls); - registerMethod(L, "Spell", "checkFloor", SpellFunctions::luaSpellCheckFloor); - } + static void init(lua_State* L); private: static int luaSpellCreate(lua_State* L); diff --git a/src/lua/functions/creatures/combat/variant_functions.cpp b/src/lua/functions/creatures/combat/variant_functions.cpp index 4723e9e8543..5a386fca803 100644 --- a/src/lua/functions/creatures/combat/variant_functions.cpp +++ b/src/lua/functions/creatures/combat/variant_functions.cpp @@ -7,35 +7,45 @@ * Website: https://docs.opentibiabr.com/ */ -#include "items/cylinder.hpp" #include "lua/functions/creatures/combat/variant_functions.hpp" + +#include "items/cylinder.hpp" #include "lua/global/lua_variant.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void VariantFunctions::init(lua_State* L) { + Lua::registerClass(L, "Variant", "", VariantFunctions::luaVariantCreate); + + Lua::registerMethod(L, "Variant", "getNumber", VariantFunctions::luaVariantGetNumber); + Lua::registerMethod(L, "Variant", "getString", VariantFunctions::luaVariantGetString); + Lua::registerMethod(L, "Variant", "getPosition", VariantFunctions::luaVariantGetPosition); +} int VariantFunctions::luaVariantCreate(lua_State* L) { // Variant(number or string or position or thing) LuaVariant variant; - if (isUserdata(L, 2)) { - if (std::shared_ptr<Thing> thing = getThing(L, 2)) { + if (Lua::isUserdata(L, 2)) { + if (const auto &thing = Lua::getThing(L, 2)) { variant.type = VARIANT_TARGETPOSITION; variant.pos = thing->getPosition(); } - } else if (isTable(L, 2)) { + } else if (Lua::isTable(L, 2)) { variant.type = VARIANT_POSITION; - variant.pos = getPosition(L, 2); - } else if (isNumber(L, 2)) { + variant.pos = Lua::getPosition(L, 2); + } else if (Lua::isNumber(L, 2)) { variant.type = VARIANT_NUMBER; - variant.number = getNumber<uint32_t>(L, 2); - } else if (isString(L, 2)) { + variant.number = Lua::getNumber<uint32_t>(L, 2); + } else if (Lua::isString(L, 2)) { variant.type = VARIANT_STRING; - variant.text = getString(L, 2); + variant.text = Lua::getString(L, 2); } - pushVariant(L, variant); + Lua::pushVariant(L, variant); return 1; } int VariantFunctions::luaVariantGetNumber(lua_State* L) { - // Variant:getNumber() - const LuaVariant &variant = getVariant(L, 1); + // Variant:Lua::getNumber() + const LuaVariant &variant = Lua::getVariant(L, 1); if (variant.type == VARIANT_NUMBER) { lua_pushnumber(L, variant.number); } else { @@ -45,23 +55,23 @@ int VariantFunctions::luaVariantGetNumber(lua_State* L) { } int VariantFunctions::luaVariantGetString(lua_State* L) { - // Variant:getString() - const LuaVariant &variant = getVariant(L, 1); + // Variant:Lua::getString() + const LuaVariant &variant = Lua::getVariant(L, 1); if (variant.type == VARIANT_STRING) { - pushString(L, variant.text); + Lua::pushString(L, variant.text); } else { - pushString(L, std::string()); + Lua::pushString(L, std::string()); } return 1; } int VariantFunctions::luaVariantGetPosition(lua_State* L) { - // Variant:getPosition() - const LuaVariant &variant = getVariant(L, 1); + // Variant:Lua::getPosition() + const LuaVariant &variant = Lua::getVariant(L, 1); if (variant.type == VARIANT_POSITION || variant.type == VARIANT_TARGETPOSITION) { - pushPosition(L, variant.pos); + Lua::pushPosition(L, variant.pos); } else { - pushPosition(L, Position()); + Lua::pushPosition(L, Position()); } return 1; } diff --git a/src/lua/functions/creatures/combat/variant_functions.hpp b/src/lua/functions/creatures/combat/variant_functions.hpp index c62bbc114a8..2ab5e29516a 100644 --- a/src/lua/functions/creatures/combat/variant_functions.hpp +++ b/src/lua/functions/creatures/combat/variant_functions.hpp @@ -9,17 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class VariantFunctions final : LuaScriptInterface { +class VariantFunctions { public: - static void init(lua_State* L) { - registerClass(L, "Variant", "", VariantFunctions::luaVariantCreate); - - registerMethod(L, "Variant", "getNumber", VariantFunctions::luaVariantGetNumber); - registerMethod(L, "Variant", "getString", VariantFunctions::luaVariantGetString); - registerMethod(L, "Variant", "getPosition", VariantFunctions::luaVariantGetPosition); - } + static void init(lua_State* L); private: static int luaVariantCreate(lua_State* L); diff --git a/src/lua/functions/creatures/creature_functions.cpp b/src/lua/functions/creatures/creature_functions.cpp index 83549818581..72b41d01928 100644 --- a/src/lua/functions/creatures/creature_functions.cpp +++ b/src/lua/functions/creatures/creature_functions.cpp @@ -7,32 +7,116 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" -#include "creatures/creature.hpp" #include "lua/functions/creatures/creature_functions.hpp" + +#include "config/configmanager.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/creature.hpp" +#include "creatures/players/player.hpp" +#include "game/game.hpp" +#include "lua/creature/creatureevent.hpp" #include "map/spectators.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void CreatureFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Creature", "", CreatureFunctions::luaCreatureCreate); + Lua::registerMetaMethod(L, "Creature", "__eq", Lua::luaUserdataCompare); + Lua::registerMethod(L, "Creature", "getEvents", CreatureFunctions::luaCreatureGetEvents); + Lua::registerMethod(L, "Creature", "registerEvent", CreatureFunctions::luaCreatureRegisterEvent); + Lua::registerMethod(L, "Creature", "unregisterEvent", CreatureFunctions::luaCreatureUnregisterEvent); + Lua::registerMethod(L, "Creature", "isRemoved", CreatureFunctions::luaCreatureIsRemoved); + Lua::registerMethod(L, "Creature", "isCreature", CreatureFunctions::luaCreatureIsCreature); + Lua::registerMethod(L, "Creature", "isInGhostMode", CreatureFunctions::luaCreatureIsInGhostMode); + Lua::registerMethod(L, "Creature", "isHealthHidden", CreatureFunctions::luaCreatureIsHealthHidden); + Lua::registerMethod(L, "Creature", "isImmune", CreatureFunctions::luaCreatureIsImmune); + Lua::registerMethod(L, "Creature", "canSee", CreatureFunctions::luaCreatureCanSee); + Lua::registerMethod(L, "Creature", "canSeeCreature", CreatureFunctions::luaCreatureCanSeeCreature); + Lua::registerMethod(L, "Creature", "getParent", CreatureFunctions::luaCreatureGetParent); + Lua::registerMethod(L, "Creature", "getId", CreatureFunctions::luaCreatureGetId); + Lua::registerMethod(L, "Creature", "getName", CreatureFunctions::luaCreatureGetName); + Lua::registerMethod(L, "Creature", "getTypeName", CreatureFunctions::luaCreatureGetTypeName); + Lua::registerMethod(L, "Creature", "getTarget", CreatureFunctions::luaCreatureGetTarget); + Lua::registerMethod(L, "Creature", "setTarget", CreatureFunctions::luaCreatureSetTarget); + Lua::registerMethod(L, "Creature", "getFollowCreature", CreatureFunctions::luaCreatureGetFollowCreature); + Lua::registerMethod(L, "Creature", "setFollowCreature", CreatureFunctions::luaCreatureSetFollowCreature); + Lua::registerMethod(L, "Creature", "reload", CreatureFunctions::luaCreatureReload); + Lua::registerMethod(L, "Creature", "getMaster", CreatureFunctions::luaCreatureGetMaster); + Lua::registerMethod(L, "Creature", "setMaster", CreatureFunctions::luaCreatureSetMaster); + Lua::registerMethod(L, "Creature", "getLight", CreatureFunctions::luaCreatureGetLight); + Lua::registerMethod(L, "Creature", "setLight", CreatureFunctions::luaCreatureSetLight); + Lua::registerMethod(L, "Creature", "getSpeed", CreatureFunctions::luaCreatureGetSpeed); + Lua::registerMethod(L, "Creature", "setSpeed", CreatureFunctions::luaCreatureSetSpeed); + Lua::registerMethod(L, "Creature", "getBaseSpeed", CreatureFunctions::luaCreatureGetBaseSpeed); + Lua::registerMethod(L, "Creature", "changeSpeed", CreatureFunctions::luaCreatureChangeSpeed); + Lua::registerMethod(L, "Creature", "setDropLoot", CreatureFunctions::luaCreatureSetDropLoot); + Lua::registerMethod(L, "Creature", "setSkillLoss", CreatureFunctions::luaCreatureSetSkillLoss); + Lua::registerMethod(L, "Creature", "getPosition", CreatureFunctions::luaCreatureGetPosition); + Lua::registerMethod(L, "Creature", "getTile", CreatureFunctions::luaCreatureGetTile); + Lua::registerMethod(L, "Creature", "getDirection", CreatureFunctions::luaCreatureGetDirection); + Lua::registerMethod(L, "Creature", "setDirection", CreatureFunctions::luaCreatureSetDirection); + Lua::registerMethod(L, "Creature", "getHealth", CreatureFunctions::luaCreatureGetHealth); + Lua::registerMethod(L, "Creature", "setHealth", CreatureFunctions::luaCreatureSetHealth); + Lua::registerMethod(L, "Creature", "addHealth", CreatureFunctions::luaCreatureAddHealth); + Lua::registerMethod(L, "Creature", "getMaxHealth", CreatureFunctions::luaCreatureGetMaxHealth); + Lua::registerMethod(L, "Creature", "setMaxHealth", CreatureFunctions::luaCreatureSetMaxHealth); + Lua::registerMethod(L, "Creature", "setHiddenHealth", CreatureFunctions::luaCreatureSetHiddenHealth); + Lua::registerMethod(L, "Creature", "isMoveLocked", CreatureFunctions::luaCreatureIsMoveLocked); + Lua::registerMethod(L, "Creature", "isDirectionLocked", CreatureFunctions::luaCreatureIsDirectionLocked); + Lua::registerMethod(L, "Creature", "setMoveLocked", CreatureFunctions::luaCreatureSetMoveLocked); + Lua::registerMethod(L, "Creature", "setDirectionLocked", CreatureFunctions::luaCreatureSetDirectionLocked); + Lua::registerMethod(L, "Creature", "getSkull", CreatureFunctions::luaCreatureGetSkull); + Lua::registerMethod(L, "Creature", "setSkull", CreatureFunctions::luaCreatureSetSkull); + Lua::registerMethod(L, "Creature", "getOutfit", CreatureFunctions::luaCreatureGetOutfit); + Lua::registerMethod(L, "Creature", "setOutfit", CreatureFunctions::luaCreatureSetOutfit); + Lua::registerMethod(L, "Creature", "getCondition", CreatureFunctions::luaCreatureGetCondition); + Lua::registerMethod(L, "Creature", "addCondition", CreatureFunctions::luaCreatureAddCondition); + Lua::registerMethod(L, "Creature", "removeCondition", CreatureFunctions::luaCreatureRemoveCondition); + Lua::registerMethod(L, "Creature", "hasCondition", CreatureFunctions::luaCreatureHasCondition); + Lua::registerMethod(L, "Creature", "remove", CreatureFunctions::luaCreatureRemove); + Lua::registerMethod(L, "Creature", "teleportTo", CreatureFunctions::luaCreatureTeleportTo); + Lua::registerMethod(L, "Creature", "say", CreatureFunctions::luaCreatureSay); + Lua::registerMethod(L, "Creature", "getDamageMap", CreatureFunctions::luaCreatureGetDamageMap); + Lua::registerMethod(L, "Creature", "getSummons", CreatureFunctions::luaCreatureGetSummons); + Lua::registerMethod(L, "Creature", "hasBeenSummoned", CreatureFunctions::luaCreatureHasBeenSummoned); + Lua::registerMethod(L, "Creature", "getDescription", CreatureFunctions::luaCreatureGetDescription); + Lua::registerMethod(L, "Creature", "getPathTo", CreatureFunctions::luaCreatureGetPathTo); + Lua::registerMethod(L, "Creature", "move", CreatureFunctions::luaCreatureMove); + Lua::registerMethod(L, "Creature", "getZoneType", CreatureFunctions::luaCreatureGetZoneType); + Lua::registerMethod(L, "Creature", "getZones", CreatureFunctions::luaCreatureGetZones); + Lua::registerMethod(L, "Creature", "setIcon", CreatureFunctions::luaCreatureSetIcon); + Lua::registerMethod(L, "Creature", "getIcon", CreatureFunctions::luaCreatureGetIcon); + Lua::registerMethod(L, "Creature", "getIcons", CreatureFunctions::luaCreatureGetIcons); + Lua::registerMethod(L, "Creature", "removeIcon", CreatureFunctions::luaCreatureRemoveIcon); + Lua::registerMethod(L, "Creature", "clearIcons", CreatureFunctions::luaCreatureClearIcons); + + CombatFunctions::init(L); + MonsterFunctions::init(L); + NpcFunctions::init(L); + PlayerFunctions::init(L); +} int CreatureFunctions::luaCreatureCreate(lua_State* L) { // Creature(id or name or userdata) std::shared_ptr<Creature> creature; - if (isNumber(L, 2)) { - creature = g_game().getCreatureByID(getNumber<uint32_t>(L, 2)); - } else if (isString(L, 2)) { - creature = g_game().getCreatureByName(getString(L, 2)); - } else if (isUserdata(L, 2)) { - LuaData_t type = getUserdataType(L, 2); - if (type != LuaData_t::Player && type != LuaData_t::Monster && type != LuaData_t::Npc) { + if (Lua::isNumber(L, 2)) { + creature = g_game().getCreatureByID(Lua::getNumber<uint32_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + creature = g_game().getCreatureByName(Lua::getString(L, 2)); + } else if (Lua::isUserdata(L, 2)) { + using enum LuaData_t; + const LuaData_t type = Lua::getUserdataType(L, 2); + if (type != Player && type != Monster && type != Npc) { lua_pushnil(L); return 1; } - creature = getUserdataShared<Creature>(L, 2); + creature = Lua::getUserdataShared<Creature>(L, 2); } else { creature = nullptr; } if (creature) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); } else { lua_pushnil(L); } @@ -41,19 +125,19 @@ int CreatureFunctions::luaCreatureCreate(lua_State* L) { int CreatureFunctions::luaCreatureGetEvents(lua_State* L) { // creature:getEvents(type) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - CreatureEventType_t eventType = getNumber<CreatureEventType_t>(L, 2); + const CreatureEventType_t eventType = Lua::getNumber<CreatureEventType_t>(L, 2); const auto eventList = creature->getCreatureEvents(eventType); lua_createtable(L, static_cast<int>(eventList.size()), 0); int index = 0; for (const auto &eventPtr : eventList) { - pushString(L, eventPtr->getName()); + Lua::pushString(L, eventPtr->getName()); lua_rawseti(L, -2, ++index); } return 1; @@ -61,10 +145,10 @@ int CreatureFunctions::luaCreatureGetEvents(lua_State* L) { int CreatureFunctions::luaCreatureRegisterEvent(lua_State* L) { // creature:registerEvent(name) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - const std::string &name = getString(L, 2); - pushBoolean(L, creature->registerCreatureEvent(name)); + const std::string &name = Lua::getString(L, 2); + Lua::pushBoolean(L, creature->registerCreatureEvent(name)); } else { lua_pushnil(L); } @@ -73,10 +157,10 @@ int CreatureFunctions::luaCreatureRegisterEvent(lua_State* L) { int CreatureFunctions::luaCreatureUnregisterEvent(lua_State* L) { // creature:unregisterEvent(name) - const std::string &name = getString(L, 2); - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const std::string &name = Lua::getString(L, 2); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->unregisterCreatureEvent(name)); + Lua::pushBoolean(L, creature->unregisterCreatureEvent(name)); } else { lua_pushnil(L); } @@ -85,9 +169,9 @@ int CreatureFunctions::luaCreatureUnregisterEvent(lua_State* L) { int CreatureFunctions::luaCreatureIsRemoved(lua_State* L) { // creature:isRemoved() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->isRemoved()); + Lua::pushBoolean(L, creature->isRemoved()); } else { lua_pushnil(L); } @@ -96,15 +180,15 @@ int CreatureFunctions::luaCreatureIsRemoved(lua_State* L) { int CreatureFunctions::luaCreatureIsCreature(lua_State* L) { // creature:isCreature() - pushBoolean(L, getUserdataShared<Creature>(L, 1) != nullptr); + Lua::pushBoolean(L, Lua::getUserdataShared<Creature>(L, 1) != nullptr); return 1; } int CreatureFunctions::luaCreatureIsInGhostMode(lua_State* L) { // creature:isInGhostMode() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->isInGhostMode()); + Lua::pushBoolean(L, creature->isInGhostMode()); } else { lua_pushnil(L); } @@ -113,9 +197,9 @@ int CreatureFunctions::luaCreatureIsInGhostMode(lua_State* L) { int CreatureFunctions::luaCreatureIsHealthHidden(lua_State* L) { // creature:isHealthHidden() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->isHealthHidden()); + Lua::pushBoolean(L, creature->isHealthHidden()); } else { lua_pushnil(L); } @@ -124,10 +208,10 @@ int CreatureFunctions::luaCreatureIsHealthHidden(lua_State* L) { int CreatureFunctions::luaCreatureCanSee(lua_State* L) { // creature:canSee(position) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - const Position &position = getPosition(L, 2); - pushBoolean(L, creature->canSee(position)); + const Position &position = Lua::getPosition(L, 2); + Lua::pushBoolean(L, creature->canSee(position)); } else { lua_pushnil(L); } @@ -136,10 +220,10 @@ int CreatureFunctions::luaCreatureCanSee(lua_State* L) { int CreatureFunctions::luaCreatureCanSeeCreature(lua_State* L) { // creature:canSeeCreature(creature) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - std::shared_ptr<Creature> otherCreature = getCreature(L, 2); - pushBoolean(L, creature->canSeeCreature(otherCreature)); + const auto &otherCreature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, creature->canSeeCreature(otherCreature)); } else { lua_pushnil(L); } @@ -148,25 +232,25 @@ int CreatureFunctions::luaCreatureCanSeeCreature(lua_State* L) { int CreatureFunctions::luaCreatureGetParent(lua_State* L) { // creature:getParent() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Cylinder> parent = creature->getParent(); + const auto &parent = creature->getParent(); if (!parent) { lua_pushnil(L); return 1; } - pushCylinder(L, parent); + Lua::pushCylinder(L, parent); return 1; } int CreatureFunctions::luaCreatureGetId(lua_State* L) { // creature:getId() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getID()); } else { @@ -177,9 +261,9 @@ int CreatureFunctions::luaCreatureGetId(lua_State* L) { int CreatureFunctions::luaCreatureGetName(lua_State* L) { // creature:getName() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushString(L, creature->getName()); + Lua::pushString(L, creature->getName()); } else { lua_pushnil(L); } @@ -188,9 +272,9 @@ int CreatureFunctions::luaCreatureGetName(lua_State* L) { int CreatureFunctions::luaCreatureGetTypeName(lua_State* L) { // creature:getTypeName() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushString(L, creature->getTypeName()); + Lua::pushString(L, creature->getTypeName()); } else { lua_pushnil(L); } @@ -199,16 +283,16 @@ int CreatureFunctions::luaCreatureGetTypeName(lua_State* L) { int CreatureFunctions::luaCreatureGetTarget(lua_State* L) { // creature:getTarget() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> target = creature->getAttackedCreature(); + const auto &target = creature->getAttackedCreature(); if (target) { - pushUserdata<Creature>(L, target); - setCreatureMetatable(L, -1, target); + Lua::pushUserdata<Creature>(L, target); + Lua::setCreatureMetatable(L, -1, target); } else { lua_pushnil(L); } @@ -217,10 +301,10 @@ int CreatureFunctions::luaCreatureGetTarget(lua_State* L) { int CreatureFunctions::luaCreatureSetTarget(lua_State* L) { // creature:setTarget(target) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - std::shared_ptr<Creature> target = getCreature(L, 2); - pushBoolean(L, creature->setAttackedCreature(target)); + const auto &target = Lua::getCreature(L, 2); + Lua::pushBoolean(L, creature->setAttackedCreature(target)); } else { lua_pushnil(L); } @@ -229,16 +313,16 @@ int CreatureFunctions::luaCreatureSetTarget(lua_State* L) { int CreatureFunctions::luaCreatureGetFollowCreature(lua_State* L) { // creature:getFollowCreature() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> followCreature = creature->getFollowCreature(); + const auto &followCreature = creature->getFollowCreature(); if (followCreature) { - pushUserdata<Creature>(L, followCreature); - setCreatureMetatable(L, -1, followCreature); + Lua::pushUserdata<Creature>(L, followCreature); + Lua::setCreatureMetatable(L, -1, followCreature); } else { lua_pushnil(L); } @@ -247,10 +331,10 @@ int CreatureFunctions::luaCreatureGetFollowCreature(lua_State* L) { int CreatureFunctions::luaCreatureSetFollowCreature(lua_State* L) { // creature:setFollowCreature(followedCreature) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - std::shared_ptr<Creature> followCreature = getCreature(L, 2); - pushBoolean(L, creature->setFollowCreature(followCreature)); + const auto &followCreature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, creature->setFollowCreature(followCreature)); } else { lua_pushnil(L); } @@ -259,45 +343,45 @@ int CreatureFunctions::luaCreatureSetFollowCreature(lua_State* L) { int CreatureFunctions::luaCreatureGetMaster(lua_State* L) { // creature:getMaster() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> master = creature->getMaster(); + const auto &master = creature->getMaster(); if (!master) { lua_pushnil(L); return 1; } - pushUserdata<Creature>(L, master); - setCreatureMetatable(L, -1, master); + Lua::pushUserdata<Creature>(L, master); + Lua::setCreatureMetatable(L, -1, master); return 1; } int CreatureFunctions::luaCreatureReload(lua_State* L) { // creature:reload() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } g_game().reloadCreature(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureSetMaster(lua_State* L) { // creature:setMaster(master) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - pushBoolean(L, creature->setMaster(getCreature(L, 2), true)); + Lua::pushBoolean(L, creature->setMaster(Lua::getCreature(L, 2), true)); // Reloading creature icon/knownCreature CreatureFunctions::luaCreatureReload(L); return 1; @@ -305,13 +389,13 @@ int CreatureFunctions::luaCreatureSetMaster(lua_State* L) { int CreatureFunctions::luaCreatureGetLight(lua_State* L) { // creature:getLight() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - LightInfo lightInfo = creature->getCreatureLight(); + const LightInfo lightInfo = creature->getCreatureLight(); lua_pushnumber(L, lightInfo.level); lua_pushnumber(L, lightInfo.color); return 2; @@ -319,24 +403,24 @@ int CreatureFunctions::luaCreatureGetLight(lua_State* L) { int CreatureFunctions::luaCreatureSetLight(lua_State* L) { // creature:setLight(color, level) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } LightInfo light; - light.color = getNumber<uint8_t>(L, 2); - light.level = getNumber<uint8_t>(L, 3); + light.color = Lua::getNumber<uint8_t>(L, 2); + light.level = Lua::getNumber<uint8_t>(L, 3); creature->setCreatureLight(light); g_game().changeLight(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureGetSpeed(lua_State* L) { // creature:getSpeed() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getSpeed()); } else { @@ -347,22 +431,22 @@ int CreatureFunctions::luaCreatureGetSpeed(lua_State* L) { int CreatureFunctions::luaCreatureSetSpeed(lua_State* L) { // creature:setSpeed(speed) - std::shared_ptr<Creature> creature = getCreature(L, 1); + const auto &creature = Lua::getCreature(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - int32_t speed = getNumber<int32_t>(L, 2); + const int32_t speed = Lua::getNumber<int32_t>(L, 2); g_game().setCreatureSpeed(creature, speed); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureGetBaseSpeed(lua_State* L) { // creature:getBaseSpeed() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getBaseSpeed()); } else { @@ -373,25 +457,25 @@ int CreatureFunctions::luaCreatureGetBaseSpeed(lua_State* L) { int CreatureFunctions::luaCreatureChangeSpeed(lua_State* L) { // creature:changeSpeed(delta) - std::shared_ptr<Creature> creature = getCreature(L, 1); + const auto &creature = Lua::getCreature(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - int32_t delta = getNumber<int32_t>(L, 2); + const int32_t delta = Lua::getNumber<int32_t>(L, 2); g_game().changeSpeed(creature, delta); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureSetDropLoot(lua_State* L) { // creature:setDropLoot(doDrop) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setDropLoot(getBoolean(L, 2)); - pushBoolean(L, true); + creature->setDropLoot(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -400,10 +484,10 @@ int CreatureFunctions::luaCreatureSetDropLoot(lua_State* L) { int CreatureFunctions::luaCreatureSetSkillLoss(lua_State* L) { // creature:setSkillLoss(skillLoss) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setSkillLoss(getBoolean(L, 2)); - pushBoolean(L, true); + creature->setSkillLoss(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -411,10 +495,10 @@ int CreatureFunctions::luaCreatureSetSkillLoss(lua_State* L) { } int CreatureFunctions::luaCreatureGetPosition(lua_State* L) { - // creature:getPosition() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + // creature:Lua::getPosition() + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushPosition(L, creature->getPosition()); + Lua::pushPosition(L, creature->getPosition()); } else { lua_pushnil(L); } @@ -423,16 +507,16 @@ int CreatureFunctions::luaCreatureGetPosition(lua_State* L) { int CreatureFunctions::luaCreatureGetTile(lua_State* L) { // creature:getTile() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Tile> tile = creature->getTile(); + const auto &tile = creature->getTile(); if (tile) { - pushUserdata<Tile>(L, tile); - setMetatable(L, -1, "Tile"); + Lua::pushUserdata<Tile>(L, tile); + Lua::setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } @@ -441,7 +525,7 @@ int CreatureFunctions::luaCreatureGetTile(lua_State* L) { int CreatureFunctions::luaCreatureGetDirection(lua_State* L) { // creature:getDirection() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getDirection()); } else { @@ -452,9 +536,9 @@ int CreatureFunctions::luaCreatureGetDirection(lua_State* L) { int CreatureFunctions::luaCreatureSetDirection(lua_State* L) { // creature:setDirection(direction) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, g_game().internalCreatureTurn(creature, getNumber<Direction>(L, 2))); + Lua::pushBoolean(L, g_game().internalCreatureTurn(creature, Lua::getNumber<Direction>(L, 2))); } else { lua_pushnil(L); } @@ -463,7 +547,7 @@ int CreatureFunctions::luaCreatureSetDirection(lua_State* L) { int CreatureFunctions::luaCreatureGetHealth(lua_State* L) { // creature:getHealth() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getHealth()); } else { @@ -474,47 +558,47 @@ int CreatureFunctions::luaCreatureGetHealth(lua_State* L) { int CreatureFunctions::luaCreatureSetHealth(lua_State* L) { // creature:setHealth(health) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - creature->health = std::min<int32_t>(getNumber<uint32_t>(L, 2), creature->healthMax); + creature->health = std::min<int32_t>(Lua::getNumber<uint32_t>(L, 2), creature->healthMax); g_game().addCreatureHealth(creature); - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendStats(); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureAddHealth(lua_State* L) { // creature:addHealth(healthChange, combatType) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } CombatDamage damage; - damage.primary.value = getNumber<int32_t>(L, 2); + damage.primary.value = Lua::getNumber<int32_t>(L, 2); if (damage.primary.value >= 0) { damage.primary.type = COMBAT_HEALING; } else if (damage.primary.value < 0) { - damage.primary.type = getNumber<CombatType_t>(L, 3); + damage.primary.type = Lua::getNumber<CombatType_t>(L, 3); } else { damage.primary.type = COMBAT_UNDEFINEDDAMAGE; } - pushBoolean(L, g_game().combatChangeHealth(nullptr, creature, damage)); + Lua::pushBoolean(L, g_game().combatChangeHealth(nullptr, creature, damage)); return 1; } int CreatureFunctions::luaCreatureGetMaxHealth(lua_State* L) { // creature:getMaxHealth() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getMaxHealth()); } else { @@ -525,31 +609,31 @@ int CreatureFunctions::luaCreatureGetMaxHealth(lua_State* L) { int CreatureFunctions::luaCreatureSetMaxHealth(lua_State* L) { // creature:setMaxHealth(maxHealth) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - creature->healthMax = getNumber<uint32_t>(L, 2); + creature->healthMax = Lua::getNumber<uint32_t>(L, 2); creature->health = std::min<int32_t>(creature->health, creature->healthMax); g_game().addCreatureHealth(creature); - std::shared_ptr<Player> player = creature->getPlayer(); + const auto &player = creature->getPlayer(); if (player) { player->sendStats(); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureSetHiddenHealth(lua_State* L) { // creature:setHiddenHealth(hide) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setHiddenHealth(getBoolean(L, 2)); + creature->setHiddenHealth(Lua::getBoolean(L, 2)); g_game().addCreatureHealth(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -558,9 +642,9 @@ int CreatureFunctions::luaCreatureSetHiddenHealth(lua_State* L) { int CreatureFunctions::luaCreatureIsMoveLocked(lua_State* L) { // creature:isMoveLocked() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->isMoveLocked()); + Lua::pushBoolean(L, creature->isMoveLocked()); } else { lua_pushnil(L); } @@ -569,10 +653,10 @@ int CreatureFunctions::luaCreatureIsMoveLocked(lua_State* L) { int CreatureFunctions::luaCreatureSetMoveLocked(lua_State* L) { // creature:setMoveLocked(moveLocked) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setMoveLocked(getBoolean(L, 2)); - pushBoolean(L, true); + creature->setMoveLocked(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -581,9 +665,9 @@ int CreatureFunctions::luaCreatureSetMoveLocked(lua_State* L) { int CreatureFunctions::luaCreatureIsDirectionLocked(lua_State* L) { // creature:isDirectionLocked() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->isDirectionLocked()); + Lua::pushBoolean(L, creature->isDirectionLocked()); } else { lua_pushnil(L); } @@ -592,10 +676,10 @@ int CreatureFunctions::luaCreatureIsDirectionLocked(lua_State* L) { int CreatureFunctions::luaCreatureSetDirectionLocked(lua_State* L) { // creature:setDirectionLocked(directionLocked) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setDirectionLocked(getBoolean(L, 2)); - pushBoolean(L, true); + creature->setDirectionLocked(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -604,7 +688,7 @@ int CreatureFunctions::luaCreatureSetDirectionLocked(lua_State* L) { int CreatureFunctions::luaCreatureGetSkull(lua_State* L) { // creature:getSkull() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getSkull()); } else { @@ -615,10 +699,10 @@ int CreatureFunctions::luaCreatureGetSkull(lua_State* L) { int CreatureFunctions::luaCreatureSetSkull(lua_State* L) { // creature:setSkull(skull) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - creature->setSkull(getNumber<Skulls_t>(L, 2)); - pushBoolean(L, true); + creature->setSkull(Lua::getNumber<Skulls_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -626,10 +710,10 @@ int CreatureFunctions::luaCreatureSetSkull(lua_State* L) { } int CreatureFunctions::luaCreatureGetOutfit(lua_State* L) { - // creature:getOutfit() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + // creature:Lua::getOutfit() + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushOutfit(L, creature->getCurrentOutfit()); + Lua::pushOutfit(L, creature->getCurrentOutfit()); } else { lua_pushnil(L); } @@ -638,9 +722,9 @@ int CreatureFunctions::luaCreatureGetOutfit(lua_State* L) { int CreatureFunctions::luaCreatureSetOutfit(lua_State* L) { // creature:setOutfit(outfit) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - Outfit_t outfit = getOutfit(L, 2); + Outfit_t outfit = Lua::getOutfit(L, 2); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && outfit.lookType != 0 && !g_game().isLookTypeRegistered(outfit.lookType)) { g_logger().warn("[CreatureFunctions::luaCreatureSetOutfit] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", outfit.lookType); return 1; @@ -648,7 +732,7 @@ int CreatureFunctions::luaCreatureSetOutfit(lua_State* L) { creature->defaultOutfit = outfit; g_game().internalCreatureChangeOutfit(creature, creature->defaultOutfit); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -657,20 +741,20 @@ int CreatureFunctions::luaCreatureSetOutfit(lua_State* L) { int CreatureFunctions::luaCreatureGetCondition(lua_State* L) { // creature:getCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0]]) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2); - ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); - uint32_t subId = getNumber<uint32_t>(L, 4, 0); + const ConditionType_t conditionType = Lua::getNumber<ConditionType_t>(L, 2); + const auto conditionId = Lua::getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); + const auto subId = Lua::getNumber<uint32_t>(L, 4, 0); - const std::shared_ptr<Condition> condition = creature->getCondition(conditionType, conditionId, subId); + const auto &condition = creature->getCondition(conditionType, conditionId, subId); if (condition) { - pushUserdata<const Condition>(L, condition); - setWeakMetatable(L, -1, "Condition"); + Lua::pushUserdata<const Condition>(L, condition); + Lua::setWeakMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } @@ -679,10 +763,10 @@ int CreatureFunctions::luaCreatureGetCondition(lua_State* L) { int CreatureFunctions::luaCreatureAddCondition(lua_State* L) { // creature:addCondition(condition) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); - std::shared_ptr<Condition> condition = getUserdataShared<Condition>(L, 2); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); + const auto &condition = Lua::getUserdataShared<Condition>(L, 2); if (creature && condition) { - pushBoolean(L, creature->addCondition(condition->clone())); + Lua::pushBoolean(L, creature->addCondition(condition->clone())); } else { lua_pushnil(L); } @@ -691,24 +775,24 @@ int CreatureFunctions::luaCreatureAddCondition(lua_State* L) { int CreatureFunctions::luaCreatureRemoveCondition(lua_State* L) { // creature:removeCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0[, force = false]]]) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2); - ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); - uint32_t subId = getNumber<uint32_t>(L, 4, 0); - const std::shared_ptr<Condition> condition = creature->getCondition(conditionType, conditionId, subId); + const ConditionType_t conditionType = Lua::getNumber<ConditionType_t>(L, 2); + const auto conditionId = Lua::getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT); + const auto subId = Lua::getNumber<uint32_t>(L, 4, 0); + const auto &condition = creature->getCondition(conditionType, conditionId, subId); if (condition) { - bool force = getBoolean(L, 5, false); + const bool force = Lua::getBoolean(L, 5, false); if (subId == 0) { creature->removeCondition(conditionType, conditionId, force); } else { creature->removeCondition(condition); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -717,30 +801,30 @@ int CreatureFunctions::luaCreatureRemoveCondition(lua_State* L) { int CreatureFunctions::luaCreatureHasCondition(lua_State* L) { // creature:hasCondition(conditionType[, subId = 0]) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2); - uint32_t subId = getNumber<uint32_t>(L, 3, 0); - pushBoolean(L, creature->hasCondition(conditionType, subId)); + const ConditionType_t conditionType = Lua::getNumber<ConditionType_t>(L, 2); + const auto subId = Lua::getNumber<uint32_t>(L, 3, 0); + Lua::pushBoolean(L, creature->hasCondition(conditionType, subId)); return 1; } int CreatureFunctions::luaCreatureIsImmune(lua_State* L) { // creature:isImmune(condition or conditionType) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - if (isNumber(L, 2)) { - pushBoolean(L, creature->isImmune(getNumber<ConditionType_t>(L, 2))); - } else if (auto condition = getUserdataShared<Condition>(L, 2)) { - pushBoolean(L, creature->isImmune(condition->getType())); + if (Lua::isNumber(L, 2)) { + Lua::pushBoolean(L, creature->isImmune(Lua::getNumber<ConditionType_t>(L, 2))); + } else if (const auto condition = Lua::getUserdataShared<Condition>(L, 2)) { + Lua::pushBoolean(L, creature->isImmune(condition->getType())); } else { lua_pushnil(L); } @@ -749,20 +833,20 @@ int CreatureFunctions::luaCreatureIsImmune(lua_State* L) { int CreatureFunctions::luaCreatureRemove(lua_State* L) { // creature:remove([forced = true]) - std::shared_ptr<Creature>* creaturePtr = getRawUserDataShared<Creature>(L, 1); + auto* creaturePtr = Lua::getRawUserDataShared<Creature>(L, 1); if (!creaturePtr) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = *creaturePtr; + const auto &creature = *creaturePtr; if (!creature) { lua_pushnil(L); return 1; } - bool forced = getBoolean(L, 2, true); - if (std::shared_ptr<Player> player = creature->getPlayer()) { + const bool forced = Lua::getBoolean(L, 2, true); + if (const auto &player = creature->getPlayer()) { if (forced) { player->removePlayer(true); } else { @@ -773,27 +857,27 @@ int CreatureFunctions::luaCreatureRemove(lua_State* L) { } *creaturePtr = nullptr; - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureTeleportTo(lua_State* L) { // creature:teleportTo(position[, pushMovement = false]) - bool pushMovement = getBoolean(L, 3, false); + const bool pushMovement = Lua::getBoolean(L, 3, false); - const Position &position = getPosition(L, 2); - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const Position &position = Lua::getPosition(L, 2); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature == nullptr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } const Position oldPosition = creature->getPosition(); - if (auto ret = g_game().internalTeleport(creature, position, pushMovement); + if (const auto ret = g_game().internalTeleport(creature, position, pushMovement); ret != RETURNVALUE_NOERROR) { g_logger().debug("[{}] Failed to teleport creature {}, on position {}, error code: {}", __FUNCTION__, creature->getName(), oldPosition.toString(), getReturnMessage(ret)); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -810,34 +894,34 @@ int CreatureFunctions::luaCreatureTeleportTo(lua_State* L) { g_game().internalCreatureTurn(creature, DIRECTION_EAST); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureSay(lua_State* L) { // creature:say(text[, type = TALKTYPE_MONSTER_SAY[, ghost = false[, target = nullptr[, position]]]]) - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); Position position; if (parameters >= 6) { - position = getPosition(L, 6); + position = Lua::getPosition(L, 6); if (!position.x || !position.y) { - reportErrorFunc("Invalid position specified."); - pushBoolean(L, false); + Lua::reportErrorFunc("Invalid position specified."); + Lua::pushBoolean(L, false); return 1; } } std::shared_ptr<Creature> target = nullptr; if (parameters >= 5) { - target = getCreature(L, 5); + target = Lua::getCreature(L, 5); } - bool ghost = getBoolean(L, 4, false); + const bool ghost = Lua::getBoolean(L, 4, false); - SpeakClasses type = getNumber<SpeakClasses>(L, 3, TALKTYPE_MONSTER_SAY); - const std::string &text = getString(L, 2); - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto type = Lua::getNumber<SpeakClasses>(L, 3, TALKTYPE_MONSTER_SAY); + const std::string &text = Lua::getString(L, 2); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; @@ -849,26 +933,26 @@ int CreatureFunctions::luaCreatureSay(lua_State* L) { } if (position.x != 0) { - pushBoolean(L, g_game().internalCreatureSay(creature, type, text, ghost, &spectators, &position)); + Lua::pushBoolean(L, g_game().internalCreatureSay(creature, type, text, ghost, &spectators, &position)); } else { - pushBoolean(L, g_game().internalCreatureSay(creature, type, text, ghost, &spectators)); + Lua::pushBoolean(L, g_game().internalCreatureSay(creature, type, text, ghost, &spectators)); } return 1; } int CreatureFunctions::luaCreatureGetDamageMap(lua_State* L) { // creature:getDamageMap() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } lua_createtable(L, creature->damageMap.size(), 0); - for (auto damageEntry : creature->damageMap) { + for (const auto damageEntry : creature->damageMap) { lua_createtable(L, 0, 2); - setField(L, "total", damageEntry.second.total); - setField(L, "ticks", damageEntry.second.ticks); + Lua::setField(L, "total", damageEntry.second.total); + Lua::setField(L, "ticks", damageEntry.second.ticks); lua_rawseti(L, -2, damageEntry.first); } return 1; @@ -876,7 +960,7 @@ int CreatureFunctions::luaCreatureGetDamageMap(lua_State* L) { int CreatureFunctions::luaCreatureGetSummons(lua_State* L) { // creature:getSummons() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; @@ -887,8 +971,8 @@ int CreatureFunctions::luaCreatureGetSummons(lua_State* L) { int index = 0; for (const auto &summon : creature->getSummons()) { if (summon) { - pushUserdata<Creature>(L, summon); - setCreatureMetatable(L, -1, summon); + Lua::pushUserdata<Creature>(L, summon); + Lua::setCreatureMetatable(L, -1, summon); lua_rawseti(L, -2, ++index); } } @@ -897,9 +981,9 @@ int CreatureFunctions::luaCreatureGetSummons(lua_State* L) { int CreatureFunctions::luaCreatureHasBeenSummoned(lua_State* L) { // creature:hasBeenSummoned() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushBoolean(L, creature->hasBeenSummoned()); + Lua::pushBoolean(L, creature->hasBeenSummoned()); } else { lua_pushnil(L); } @@ -909,10 +993,10 @@ int CreatureFunctions::luaCreatureHasBeenSummoned(lua_State* L) { int CreatureFunctions::luaCreatureGetDescription(lua_State* L) { // creature:getDescription(distance) - int32_t distance = getNumber<int32_t>(L, 2); - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const int32_t distance = Lua::getNumber<int32_t>(L, 2); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { - pushString(L, creature->getDescription(distance)); + Lua::pushString(L, creature->getDescription(distance)); } else { lua_pushnil(L); } @@ -921,32 +1005,32 @@ int CreatureFunctions::luaCreatureGetDescription(lua_State* L) { int CreatureFunctions::luaCreatureGetPathTo(lua_State* L) { // creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - const Position &position = getPosition(L, 2); + const Position &position = Lua::getPosition(L, 2); FindPathParams fpp; - fpp.minTargetDist = getNumber<int32_t>(L, 3, 0); - fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1); - fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch); - fpp.clearSight = getBoolean(L, 6, fpp.clearSight); - fpp.maxSearchDist = getNumber<int32_t>(L, 7, fpp.maxSearchDist); + fpp.minTargetDist = Lua::getNumber<int32_t>(L, 3, 0); + fpp.maxTargetDist = Lua::getNumber<int32_t>(L, 4, 1); + fpp.fullPathSearch = Lua::getBoolean(L, 5, fpp.fullPathSearch); + fpp.clearSight = Lua::getBoolean(L, 6, fpp.clearSight); + fpp.maxSearchDist = Lua::getNumber<int32_t>(L, 7, fpp.maxSearchDist); std::vector<Direction> dirList; if (creature->getPathTo(position, dirList, fpp)) { lua_newtable(L); int index = 0; - for (Direction dir : dirList) { + for (const Direction dir : dirList) { lua_pushnumber(L, dir); lua_rawseti(L, -2, ++index); } } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } @@ -954,33 +1038,33 @@ int CreatureFunctions::luaCreatureGetPathTo(lua_State* L) { int CreatureFunctions::luaCreatureMove(lua_State* L) { // creature:move(direction) // creature:move(tile[, flags = 0]) - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { lua_pushnil(L); return 1; } - if (isNumber(L, 2)) { - Direction direction = getNumber<Direction>(L, 2); + if (Lua::isNumber(L, 2)) { + const Direction direction = Lua::getNumber<Direction>(L, 2); if (direction > DIRECTION_LAST) { lua_pushnil(L); return 1; } lua_pushnumber(L, g_game().internalMoveCreature(creature, direction, FLAG_NOLIMIT)); } else { - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 2); + const auto &tile = Lua::getUserdataShared<Tile>(L, 2); if (!tile) { lua_pushnil(L); return 1; } - lua_pushnumber(L, g_game().internalMoveCreature(creature, tile, getNumber<uint32_t>(L, 3))); + lua_pushnumber(L, g_game().internalMoveCreature(creature, tile, Lua::getNumber<uint32_t>(L, 3))); } return 1; } int CreatureFunctions::luaCreatureGetZoneType(lua_State* L) { // creature:getZoneType() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature) { lua_pushnumber(L, creature->getZoneType()); } else { @@ -991,7 +1075,7 @@ int CreatureFunctions::luaCreatureGetZoneType(lua_State* L) { int CreatureFunctions::luaCreatureGetZones(lua_State* L) { // creature:getZones() - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (creature == nullptr) { lua_pushnil(L); return 1; @@ -1000,10 +1084,10 @@ int CreatureFunctions::luaCreatureGetZones(lua_State* L) { const auto zones = creature->getZones(); lua_createtable(L, static_cast<int>(zones.size()), 0); int index = 0; - for (auto zone : zones) { + for (const auto &zone : zones) { index++; - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); lua_rawseti(L, -2, index); } return 1; @@ -1011,35 +1095,35 @@ int CreatureFunctions::luaCreatureGetZones(lua_State* L) { int CreatureFunctions::luaCreatureSetIcon(lua_State* L) { // creature:setIcon(key, category, icon[, number]) - auto creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto key = getString(L, 2); - const auto category = getNumber<CreatureIconCategory_t>(L, 3); - const auto count = getNumber<uint16_t>(L, 5, 0); + const auto key = Lua::getString(L, 2); + const auto category = Lua::getNumber<CreatureIconCategory_t>(L, 3); + const auto count = Lua::getNumber<uint16_t>(L, 5, 0); CreatureIcon creatureIcon; if (category == CreatureIconCategory_t::Modifications) { - auto icon = getNumber<CreatureIconModifications_t>(L, 4); + const auto icon = Lua::getNumber<CreatureIconModifications_t>(L, 4); creatureIcon = CreatureIcon(icon, count); } else { - auto icon = getNumber<CreatureIconQuests_t>(L, 4); + const auto icon = Lua::getNumber<CreatureIconQuests_t>(L, 4); creatureIcon = CreatureIcon(icon, count); } creature->setIcon(key, creatureIcon); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureGetIcons(lua_State* L) { // creature:getIcons() - const auto creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -1047,9 +1131,9 @@ int CreatureFunctions::luaCreatureGetIcons(lua_State* L) { lua_createtable(L, static_cast<int>(icons.size()), 0); for (auto &icon : icons) { lua_createtable(L, 0, 3); - setField(L, "category", static_cast<uint8_t>(icon.category)); - setField(L, "icon", icon.serialize()); - setField(L, "count", icon.count); + Lua::setField(L, "category", static_cast<uint8_t>(icon.category)); + Lua::setField(L, "icon", icon.serialize()); + Lua::setField(L, "count", icon.count); lua_rawseti(L, -2, static_cast<int>(icon.category)); } return 1; @@ -1057,19 +1141,19 @@ int CreatureFunctions::luaCreatureGetIcons(lua_State* L) { int CreatureFunctions::luaCreatureGetIcon(lua_State* L) { // creature:getIcon(key) - const auto creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto key = getString(L, 2); + const auto key = Lua::getString(L, 2); auto icon = creature->getIcon(key); if (icon.isSet()) { lua_createtable(L, 0, 3); - setField(L, "category", static_cast<uint8_t>(icon.category)); - setField(L, "icon", icon.serialize()); - setField(L, "count", icon.count); + Lua::setField(L, "category", static_cast<uint8_t>(icon.category)); + Lua::setField(L, "icon", icon.serialize()); + Lua::setField(L, "count", icon.count); } else { lua_pushnil(L); } @@ -1078,27 +1162,27 @@ int CreatureFunctions::luaCreatureGetIcon(lua_State* L) { int CreatureFunctions::luaCreatureRemoveIcon(lua_State* L) { // creature:removeIcon(key) - auto creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto key = getString(L, 2); + const auto key = Lua::getString(L, 2); creature->removeIcon(key); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int CreatureFunctions::luaCreatureClearIcons(lua_State* L) { // creature:clearIcons() - auto creature = getUserdataShared<Creature>(L, 1); + const auto &creature = Lua::getUserdataShared<Creature>(L, 1); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } creature->clearIcons(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/creatures/creature_functions.hpp b/src/lua/functions/creatures/creature_functions.hpp index 0876bb72901..8d1c5b8ce52 100644 --- a/src/lua/functions/creatures/creature_functions.hpp +++ b/src/lua/functions/creatures/creature_functions.hpp @@ -13,86 +13,9 @@ #include "lua/functions/creatures/monster/monster_functions.hpp" #include "lua/functions/creatures/npc/npc_functions.hpp" #include "lua/functions/creatures/player/player_functions.hpp" -#include "lua/scripts/luascript.hpp" - -class CreatureFunctions final : LuaScriptInterface { +class CreatureFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Creature", "", CreatureFunctions::luaCreatureCreate); - registerMetaMethod(L, "Creature", "__eq", CreatureFunctions::luaUserdataCompare); - registerMethod(L, "Creature", "getEvents", CreatureFunctions::luaCreatureGetEvents); - registerMethod(L, "Creature", "registerEvent", CreatureFunctions::luaCreatureRegisterEvent); - registerMethod(L, "Creature", "unregisterEvent", CreatureFunctions::luaCreatureUnregisterEvent); - registerMethod(L, "Creature", "isRemoved", CreatureFunctions::luaCreatureIsRemoved); - registerMethod(L, "Creature", "isCreature", CreatureFunctions::luaCreatureIsCreature); - registerMethod(L, "Creature", "isInGhostMode", CreatureFunctions::luaCreatureIsInGhostMode); - registerMethod(L, "Creature", "isHealthHidden", CreatureFunctions::luaCreatureIsHealthHidden); - registerMethod(L, "Creature", "isImmune", CreatureFunctions::luaCreatureIsImmune); - registerMethod(L, "Creature", "canSee", CreatureFunctions::luaCreatureCanSee); - registerMethod(L, "Creature", "canSeeCreature", CreatureFunctions::luaCreatureCanSeeCreature); - registerMethod(L, "Creature", "getParent", CreatureFunctions::luaCreatureGetParent); - registerMethod(L, "Creature", "getId", CreatureFunctions::luaCreatureGetId); - registerMethod(L, "Creature", "getName", CreatureFunctions::luaCreatureGetName); - registerMethod(L, "Creature", "getTypeName", CreatureFunctions::luaCreatureGetTypeName); - registerMethod(L, "Creature", "getTarget", CreatureFunctions::luaCreatureGetTarget); - registerMethod(L, "Creature", "setTarget", CreatureFunctions::luaCreatureSetTarget); - registerMethod(L, "Creature", "getFollowCreature", CreatureFunctions::luaCreatureGetFollowCreature); - registerMethod(L, "Creature", "setFollowCreature", CreatureFunctions::luaCreatureSetFollowCreature); - registerMethod(L, "Creature", "reload", CreatureFunctions::luaCreatureReload); - registerMethod(L, "Creature", "getMaster", CreatureFunctions::luaCreatureGetMaster); - registerMethod(L, "Creature", "setMaster", CreatureFunctions::luaCreatureSetMaster); - registerMethod(L, "Creature", "getLight", CreatureFunctions::luaCreatureGetLight); - registerMethod(L, "Creature", "setLight", CreatureFunctions::luaCreatureSetLight); - registerMethod(L, "Creature", "getSpeed", CreatureFunctions::luaCreatureGetSpeed); - registerMethod(L, "Creature", "setSpeed", CreatureFunctions::luaCreatureSetSpeed); - registerMethod(L, "Creature", "getBaseSpeed", CreatureFunctions::luaCreatureGetBaseSpeed); - registerMethod(L, "Creature", "changeSpeed", CreatureFunctions::luaCreatureChangeSpeed); - registerMethod(L, "Creature", "setDropLoot", CreatureFunctions::luaCreatureSetDropLoot); - registerMethod(L, "Creature", "setSkillLoss", CreatureFunctions::luaCreatureSetSkillLoss); - registerMethod(L, "Creature", "getPosition", CreatureFunctions::luaCreatureGetPosition); - registerMethod(L, "Creature", "getTile", CreatureFunctions::luaCreatureGetTile); - registerMethod(L, "Creature", "getDirection", CreatureFunctions::luaCreatureGetDirection); - registerMethod(L, "Creature", "setDirection", CreatureFunctions::luaCreatureSetDirection); - registerMethod(L, "Creature", "getHealth", CreatureFunctions::luaCreatureGetHealth); - registerMethod(L, "Creature", "setHealth", CreatureFunctions::luaCreatureSetHealth); - registerMethod(L, "Creature", "addHealth", CreatureFunctions::luaCreatureAddHealth); - registerMethod(L, "Creature", "getMaxHealth", CreatureFunctions::luaCreatureGetMaxHealth); - registerMethod(L, "Creature", "setMaxHealth", CreatureFunctions::luaCreatureSetMaxHealth); - registerMethod(L, "Creature", "setHiddenHealth", CreatureFunctions::luaCreatureSetHiddenHealth); - registerMethod(L, "Creature", "isMoveLocked", CreatureFunctions::luaCreatureIsMoveLocked); - registerMethod(L, "Creature", "isDirectionLocked", CreatureFunctions::luaCreatureIsDirectionLocked); - registerMethod(L, "Creature", "setMoveLocked", CreatureFunctions::luaCreatureSetMoveLocked); - registerMethod(L, "Creature", "setDirectionLocked", CreatureFunctions::luaCreatureSetDirectionLocked); - registerMethod(L, "Creature", "getSkull", CreatureFunctions::luaCreatureGetSkull); - registerMethod(L, "Creature", "setSkull", CreatureFunctions::luaCreatureSetSkull); - registerMethod(L, "Creature", "getOutfit", CreatureFunctions::luaCreatureGetOutfit); - registerMethod(L, "Creature", "setOutfit", CreatureFunctions::luaCreatureSetOutfit); - registerMethod(L, "Creature", "getCondition", CreatureFunctions::luaCreatureGetCondition); - registerMethod(L, "Creature", "addCondition", CreatureFunctions::luaCreatureAddCondition); - registerMethod(L, "Creature", "removeCondition", CreatureFunctions::luaCreatureRemoveCondition); - registerMethod(L, "Creature", "hasCondition", CreatureFunctions::luaCreatureHasCondition); - registerMethod(L, "Creature", "remove", CreatureFunctions::luaCreatureRemove); - registerMethod(L, "Creature", "teleportTo", CreatureFunctions::luaCreatureTeleportTo); - registerMethod(L, "Creature", "say", CreatureFunctions::luaCreatureSay); - registerMethod(L, "Creature", "getDamageMap", CreatureFunctions::luaCreatureGetDamageMap); - registerMethod(L, "Creature", "getSummons", CreatureFunctions::luaCreatureGetSummons); - registerMethod(L, "Creature", "hasBeenSummoned", CreatureFunctions::luaCreatureHasBeenSummoned); - registerMethod(L, "Creature", "getDescription", CreatureFunctions::luaCreatureGetDescription); - registerMethod(L, "Creature", "getPathTo", CreatureFunctions::luaCreatureGetPathTo); - registerMethod(L, "Creature", "move", CreatureFunctions::luaCreatureMove); - registerMethod(L, "Creature", "getZoneType", CreatureFunctions::luaCreatureGetZoneType); - registerMethod(L, "Creature", "getZones", CreatureFunctions::luaCreatureGetZones); - registerMethod(L, "Creature", "setIcon", CreatureFunctions::luaCreatureSetIcon); - registerMethod(L, "Creature", "getIcon", CreatureFunctions::luaCreatureGetIcon); - registerMethod(L, "Creature", "getIcons", CreatureFunctions::luaCreatureGetIcons); - registerMethod(L, "Creature", "removeIcon", CreatureFunctions::luaCreatureRemoveIcon); - registerMethod(L, "Creature", "clearIcons", CreatureFunctions::luaCreatureClearIcons); - - CombatFunctions::init(L); - MonsterFunctions::init(L); - NpcFunctions::init(L); - PlayerFunctions::init(L); - } + static void init(lua_State* L); private: static int luaCreatureCreate(lua_State* L); diff --git a/src/lua/functions/creatures/monster/charm_functions.cpp b/src/lua/functions/creatures/monster/charm_functions.cpp index 492820b76fa..88d27314431 100644 --- a/src/lua/functions/creatures/monster/charm_functions.cpp +++ b/src/lua/functions/creatures/monster/charm_functions.cpp @@ -7,20 +7,40 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/monster/charm_functions.hpp" + #include "game/game.hpp" #include "io/iobestiary.hpp" -#include "lua/functions/creatures/monster/charm_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void CharmFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Charm", "", CharmFunctions::luaCharmCreate); + Lua::registerMetaMethod(L, "Charm", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Charm", "name", CharmFunctions::luaCharmName); + Lua::registerMethod(L, "Charm", "description", CharmFunctions::luaCharmDescription); + Lua::registerMethod(L, "Charm", "type", CharmFunctions::luaCharmType); + Lua::registerMethod(L, "Charm", "points", CharmFunctions::luaCharmPoints); + Lua::registerMethod(L, "Charm", "damageType", CharmFunctions::luaCharmDamageType); + Lua::registerMethod(L, "Charm", "percentage", CharmFunctions::luaCharmPercentage); + Lua::registerMethod(L, "Charm", "chance", CharmFunctions::luaCharmChance); + Lua::registerMethod(L, "Charm", "messageCancel", CharmFunctions::luaCharmMessageCancel); + Lua::registerMethod(L, "Charm", "messageServerLog", CharmFunctions::luaCharmMessageServerLog); + Lua::registerMethod(L, "Charm", "effect", CharmFunctions::luaCharmEffect); + Lua::registerMethod(L, "Charm", "castSound", CharmFunctions::luaCharmCastSound); + Lua::registerMethod(L, "Charm", "impactSound", CharmFunctions::luaCharmImpactSound); +} int CharmFunctions::luaCharmCreate(lua_State* L) { // charm(id) - if (isNumber(L, 2)) { - charmRune_t charmid = getNumber<charmRune_t>(L, 2); + if (Lua::isNumber(L, 2)) { + const charmRune_t charmid = Lua::getNumber<charmRune_t>(L, 2); const auto charmList = g_game().getCharmList(); for (const auto &charm : charmList) { if (charm->id == charmid) { - pushUserdata<Charm>(L, charm); - setMetatable(L, -1, "Charm"); - pushBoolean(L, true); + Lua::pushUserdata<Charm>(L, charm); + Lua::setMetatable(L, -1, "Charm"); + Lua::pushBoolean(L, true); } } } @@ -31,144 +51,144 @@ int CharmFunctions::luaCharmCreate(lua_State* L) { int CharmFunctions::luaCharmName(lua_State* L) { // get: charm:name() set: charm:name(string) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { - pushString(L, charm->name); + Lua::pushString(L, charm->name); } else { - charm->name = getString(L, 2); - pushBoolean(L, true); + charm->name = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmDescription(lua_State* L) { // get: charm:description() set: charm:description(string) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { - pushString(L, charm->description); + Lua::pushString(L, charm->description); } else { - charm->description = getString(L, 2); - pushBoolean(L, true); + charm->description = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmType(lua_State* L) { // get: charm:type() set: charm:type(charm_t) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->type); } else { - charm->type = getNumber<charm_t>(L, 2); - pushBoolean(L, true); + charm->type = Lua::getNumber<charm_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmPoints(lua_State* L) { // get: charm:points() set: charm:points(value) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->points); } else { - charm->points = getNumber<int16_t>(L, 2); - pushBoolean(L, true); + charm->points = Lua::getNumber<int16_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmDamageType(lua_State* L) { // get: charm:damageType() set: charm:damageType(type) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->dmgtype); } else { - charm->dmgtype = getNumber<CombatType_t>(L, 2); - pushBoolean(L, true); + charm->dmgtype = Lua::getNumber<CombatType_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmPercentage(lua_State* L) { // get: charm:percentage() set: charm:percentage(value) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->percent); } else { - charm->percent = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + charm->percent = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmChance(lua_State* L) { // get: charm:chance() set: charm:chance(value) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->chance); } else { - charm->chance = getNumber<int8_t>(L, 2); - pushBoolean(L, true); + charm->chance = Lua::getNumber<int8_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmMessageCancel(lua_State* L) { // get: charm:messageCancel() set: charm:messageCancel(string) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { - pushString(L, charm->cancelMsg); + Lua::pushString(L, charm->cancelMsg); } else { - charm->cancelMsg = getString(L, 2); - pushBoolean(L, true); + charm->cancelMsg = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmMessageServerLog(lua_State* L) { // get: charm:messageServerLog() set: charm:messageServerLog(string) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { - pushString(L, charm->logMsg); + Lua::pushString(L, charm->logMsg); } else { - charm->logMsg = getString(L, 2); - pushBoolean(L, true); + charm->logMsg = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmEffect(lua_State* L) { // get: charm:effect() set: charm:effect(value) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, charm->effect); } else { - charm->effect = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + charm->effect = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmCastSound(lua_State* L) { // get: charm:castSound() set: charm:castSound(sound) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<lua_Number>(charm->soundCastEffect)); } else { - charm->soundCastEffect = getNumber<SoundEffect_t>(L, 2); - pushBoolean(L, true); + charm->soundCastEffect = Lua::getNumber<SoundEffect_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int CharmFunctions::luaCharmImpactSound(lua_State* L) { // get: charm:impactSound() set: charm:impactSound(sound) - const auto charm = getUserdataShared<Charm>(L, 1); + const auto &charm = Lua::getUserdataShared<Charm>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<lua_Number>(charm->soundImpactEffect)); } else { - charm->soundImpactEffect = getNumber<SoundEffect_t>(L, 2); - pushBoolean(L, true); + charm->soundImpactEffect = Lua::getNumber<SoundEffect_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } diff --git a/src/lua/functions/creatures/monster/charm_functions.hpp b/src/lua/functions/creatures/monster/charm_functions.hpp index 7be1c8de635..10b9f96f124 100644 --- a/src/lua/functions/creatures/monster/charm_functions.hpp +++ b/src/lua/functions/creatures/monster/charm_functions.hpp @@ -9,27 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class CharmFunctions final : LuaScriptInterface { +class CharmFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Charm", "", CharmFunctions::luaCharmCreate); - registerMetaMethod(L, "Charm", "__eq", CharmFunctions::luaUserdataCompare); - - registerMethod(L, "Charm", "name", CharmFunctions::luaCharmName); - registerMethod(L, "Charm", "description", CharmFunctions::luaCharmDescription); - registerMethod(L, "Charm", "type", CharmFunctions::luaCharmType); - registerMethod(L, "Charm", "points", CharmFunctions::luaCharmPoints); - registerMethod(L, "Charm", "damageType", CharmFunctions::luaCharmDamageType); - registerMethod(L, "Charm", "percentage", CharmFunctions::luaCharmPercentage); - registerMethod(L, "Charm", "chance", CharmFunctions::luaCharmChance); - registerMethod(L, "Charm", "messageCancel", CharmFunctions::luaCharmMessageCancel); - registerMethod(L, "Charm", "messageServerLog", CharmFunctions::luaCharmMessageServerLog); - registerMethod(L, "Charm", "effect", CharmFunctions::luaCharmEffect); - registerMethod(L, "Charm", "castSound", CharmFunctions::luaCharmCastSound); - registerMethod(L, "Charm", "impactSound", CharmFunctions::luaCharmImpactSound); - } + static void init(lua_State* L); private: static int luaCharmCreate(lua_State* L); diff --git a/src/lua/functions/creatures/monster/loot_functions.cpp b/src/lua/functions/creatures/monster/loot_functions.cpp index e05d86b6340..87e7c8c2588 100644 --- a/src/lua/functions/creatures/monster/loot_functions.cpp +++ b/src/lua/functions/creatures/monster/loot_functions.cpp @@ -7,24 +7,51 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/monsters/monsters.hpp" #include "lua/functions/creatures/monster/loot_functions.hpp" +#include "creatures/monsters/monsters.hpp" +#include "items/item.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void LootFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Loot", "", LootFunctions::luaCreateLoot); + + Lua::registerMethod(L, "Loot", "setId", LootFunctions::luaLootSetId); + Lua::registerMethod(L, "Loot", "setIdFromName", LootFunctions::luaLootSetIdFromName); + Lua::registerMethod(L, "Loot", "setMinCount", LootFunctions::luaLootSetMinCount); + Lua::registerMethod(L, "Loot", "setMaxCount", LootFunctions::luaLootSetMaxCount); + Lua::registerMethod(L, "Loot", "setSubType", LootFunctions::luaLootSetSubType); + Lua::registerMethod(L, "Loot", "setChance", LootFunctions::luaLootSetChance); + Lua::registerMethod(L, "Loot", "setActionId", LootFunctions::luaLootSetActionId); + Lua::registerMethod(L, "Loot", "setText", LootFunctions::luaLootSetText); + Lua::registerMethod(L, "Loot", "setNameItem", LootFunctions::luaLootSetNameItem); + Lua::registerMethod(L, "Loot", "setArticle", LootFunctions::luaLootSetArticle); + Lua::registerMethod(L, "Loot", "setAttack", LootFunctions::luaLootSetAttack); + Lua::registerMethod(L, "Loot", "setDefense", LootFunctions::luaLootSetDefense); + Lua::registerMethod(L, "Loot", "setExtraDefense", LootFunctions::luaLootSetExtraDefense); + Lua::registerMethod(L, "Loot", "setArmor", LootFunctions::luaLootSetArmor); + Lua::registerMethod(L, "Loot", "setShootRange", LootFunctions::luaLootSetShootRange); + Lua::registerMethod(L, "Loot", "setHitChance", LootFunctions::luaLootSetHitChance); + Lua::registerMethod(L, "Loot", "setUnique", LootFunctions::luaLootSetUnique); + Lua::registerMethod(L, "Loot", "addChildLoot", LootFunctions::luaLootAddChildLoot); +} + int LootFunctions::luaCreateLoot(lua_State* L) { // Loot() will create a new loot item - const auto loot = std::make_shared<Loot>(); - pushUserdata<Loot>(L, loot); - setMetatable(L, -1, "Loot"); + auto loot = std::make_shared<Loot>(); + Lua::pushUserdata<Loot>(L, loot); + Lua::setMetatable(L, -1, "Loot"); return 1; } int LootFunctions::luaLootSetId(lua_State* L) { // loot:setId(id) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - if (isNumber(L, 2)) { - loot->lootBlock.id = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + if (Lua::isNumber(L, 2)) { + loot->lootBlock.id = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { g_logger().warn("[LootFunctions::luaLootSetId] - " "Unknown loot item loot, int value expected"); @@ -38,10 +65,10 @@ int LootFunctions::luaLootSetId(lua_State* L) { int LootFunctions::luaLootSetIdFromName(lua_State* L) { // loot:setIdFromName(name) - const auto loot = getUserdataShared<Loot>(L, 1); - if (loot && isString(L, 2)) { - auto name = getString(L, 2); - auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name)); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); + if (loot && Lua::isString(L, 2)) { + auto name = Lua::getString(L, 2); + const auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name)); if (ids.first == Item::items.nameToItems.cend()) { g_logger().warn("[LootFunctions::luaLootSetIdFromName] - " @@ -60,7 +87,7 @@ int LootFunctions::luaLootSetIdFromName(lua_State* L) { } loot->lootBlock.id = ids.first->second; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { g_logger().warn("[LootFunctions::luaLootSetIdFromName] - " "Unknown loot item loot, string value expected"); @@ -71,10 +98,10 @@ int LootFunctions::luaLootSetIdFromName(lua_State* L) { int LootFunctions::luaLootSetSubType(lua_State* L) { // loot:setSubType(type) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.subType = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.subType = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -83,10 +110,10 @@ int LootFunctions::luaLootSetSubType(lua_State* L) { int LootFunctions::luaLootSetChance(lua_State* L) { // loot:setChance(chance) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.chance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.chance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -95,10 +122,10 @@ int LootFunctions::luaLootSetChance(lua_State* L) { int LootFunctions::luaLootSetMinCount(lua_State* L) { // loot:setMinCount(min) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.countmin = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.countmin = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -107,10 +134,10 @@ int LootFunctions::luaLootSetMinCount(lua_State* L) { int LootFunctions::luaLootSetMaxCount(lua_State* L) { // loot:setMaxCount(max) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.countmax = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.countmax = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -119,10 +146,10 @@ int LootFunctions::luaLootSetMaxCount(lua_State* L) { int LootFunctions::luaLootSetActionId(lua_State* L) { // loot:setActionId(actionid) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.actionId = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.actionId = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -131,10 +158,10 @@ int LootFunctions::luaLootSetActionId(lua_State* L) { int LootFunctions::luaLootSetText(lua_State* L) { // loot:setText(text) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.text = getString(L, 2); - pushBoolean(L, true); + loot->lootBlock.text = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -143,10 +170,10 @@ int LootFunctions::luaLootSetText(lua_State* L) { int LootFunctions::luaLootSetNameItem(lua_State* L) { // loot:setNameItem(name) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.name = getString(L, 2); - pushBoolean(L, true); + loot->lootBlock.name = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -155,10 +182,10 @@ int LootFunctions::luaLootSetNameItem(lua_State* L) { int LootFunctions::luaLootSetArticle(lua_State* L) { // loot:setArticle(article) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.article = getString(L, 2); - pushBoolean(L, true); + loot->lootBlock.article = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -167,10 +194,10 @@ int LootFunctions::luaLootSetArticle(lua_State* L) { int LootFunctions::luaLootSetAttack(lua_State* L) { // loot:setAttack(attack) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.attack = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.attack = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -179,10 +206,10 @@ int LootFunctions::luaLootSetAttack(lua_State* L) { int LootFunctions::luaLootSetDefense(lua_State* L) { // loot:setDefense(defense) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.defense = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.defense = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -191,10 +218,10 @@ int LootFunctions::luaLootSetDefense(lua_State* L) { int LootFunctions::luaLootSetExtraDefense(lua_State* L) { // loot:setExtraDefense(defense) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.extraDefense = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.extraDefense = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -203,10 +230,10 @@ int LootFunctions::luaLootSetExtraDefense(lua_State* L) { int LootFunctions::luaLootSetArmor(lua_State* L) { // loot:setArmor(armor) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.armor = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.armor = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -215,10 +242,10 @@ int LootFunctions::luaLootSetArmor(lua_State* L) { int LootFunctions::luaLootSetShootRange(lua_State* L) { // loot:setShootRange(range) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.shootRange = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.shootRange = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -227,10 +254,10 @@ int LootFunctions::luaLootSetShootRange(lua_State* L) { int LootFunctions::luaLootSetHitChance(lua_State* L) { // loot:setHitChance(chance) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - loot->lootBlock.hitChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + loot->lootBlock.hitChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -239,13 +266,13 @@ int LootFunctions::luaLootSetHitChance(lua_State* L) { int LootFunctions::luaLootSetUnique(lua_State* L) { // loot:setUnique(bool) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { if (lua_gettop(L) == 1) { - pushBoolean(L, loot->lootBlock.unique); + Lua::pushBoolean(L, loot->lootBlock.unique); } else { - loot->lootBlock.unique = getBoolean(L, 2); - pushBoolean(L, true); + loot->lootBlock.unique = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -255,14 +282,14 @@ int LootFunctions::luaLootSetUnique(lua_State* L) { int LootFunctions::luaLootAddChildLoot(lua_State* L) { // loot:addChildLoot(loot) - const auto loot = getUserdataShared<Loot>(L, 1); + const auto &loot = Lua::getUserdataShared<Loot>(L, 1); if (loot) { - const auto childLoot = getUserdata<Loot>(L, 2); + const auto childLoot = Lua::getUserdata<Loot>(L, 2); if (childLoot) { loot->lootBlock.childLoot.push_back(childLoot->lootBlock); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } } else { lua_pushnil(L); diff --git a/src/lua/functions/creatures/monster/loot_functions.hpp b/src/lua/functions/creatures/monster/loot_functions.hpp index 77059307a66..faa9abc2ef1 100644 --- a/src/lua/functions/creatures/monster/loot_functions.hpp +++ b/src/lua/functions/creatures/monster/loot_functions.hpp @@ -9,32 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class LootFunctions final : LuaScriptInterface { +class LootFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Loot", "", LootFunctions::luaCreateLoot); - - registerMethod(L, "Loot", "setId", LootFunctions::luaLootSetId); - registerMethod(L, "Loot", "setIdFromName", LootFunctions::luaLootSetIdFromName); - registerMethod(L, "Loot", "setMinCount", LootFunctions::luaLootSetMinCount); - registerMethod(L, "Loot", "setMaxCount", LootFunctions::luaLootSetMaxCount); - registerMethod(L, "Loot", "setSubType", LootFunctions::luaLootSetSubType); - registerMethod(L, "Loot", "setChance", LootFunctions::luaLootSetChance); - registerMethod(L, "Loot", "setActionId", LootFunctions::luaLootSetActionId); - registerMethod(L, "Loot", "setText", LootFunctions::luaLootSetText); - registerMethod(L, "Loot", "setNameItem", LootFunctions::luaLootSetNameItem); - registerMethod(L, "Loot", "setArticle", LootFunctions::luaLootSetArticle); - registerMethod(L, "Loot", "setAttack", LootFunctions::luaLootSetAttack); - registerMethod(L, "Loot", "setDefense", LootFunctions::luaLootSetDefense); - registerMethod(L, "Loot", "setExtraDefense", LootFunctions::luaLootSetExtraDefense); - registerMethod(L, "Loot", "setArmor", LootFunctions::luaLootSetArmor); - registerMethod(L, "Loot", "setShootRange", LootFunctions::luaLootSetShootRange); - registerMethod(L, "Loot", "setHitChance", LootFunctions::luaLootSetHitChance); - registerMethod(L, "Loot", "setUnique", LootFunctions::luaLootSetUnique); - registerMethod(L, "Loot", "addChildLoot", LootFunctions::luaLootAddChildLoot); - } + static void init(lua_State* L); private: static int luaCreateLoot(lua_State* L); diff --git a/src/lua/functions/creatures/monster/monster_functions.cpp b/src/lua/functions/creatures/monster/monster_functions.cpp index cddbca49830..3f5d0c25ea8 100644 --- a/src/lua/functions/creatures/monster/monster_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_functions.cpp @@ -7,32 +7,96 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" +#include "lua/functions/creatures/monster/monster_functions.hpp" + +#include "config/configmanager.hpp" #include "creatures/creature.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/monsters/monsters.hpp" -#include "lua/functions/creatures/monster/monster_functions.hpp" -#include "map/spectators.hpp" +#include "creatures/players/player.hpp" +#include "game/game.hpp" #include "game/scheduling/events_scheduler.hpp" +#include "map/spectators.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void MonsterFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Monster", "Creature", MonsterFunctions::luaMonsterCreate); + Lua::registerMetaMethod(L, "Monster", "__eq", Lua::luaUserdataCompare); + Lua::registerMethod(L, "Monster", "isMonster", MonsterFunctions::luaMonsterIsMonster); + Lua::registerMethod(L, "Monster", "getType", MonsterFunctions::luaMonsterGetType); + Lua::registerMethod(L, "Monster", "setType", MonsterFunctions::luaMonsterSetType); + Lua::registerMethod(L, "Monster", "getSpawnPosition", MonsterFunctions::luaMonsterGetSpawnPosition); + Lua::registerMethod(L, "Monster", "isInSpawnRange", MonsterFunctions::luaMonsterIsInSpawnRange); + Lua::registerMethod(L, "Monster", "isIdle", MonsterFunctions::luaMonsterIsIdle); + Lua::registerMethod(L, "Monster", "setIdle", MonsterFunctions::luaMonsterSetIdle); + Lua::registerMethod(L, "Monster", "isTarget", MonsterFunctions::luaMonsterIsTarget); + Lua::registerMethod(L, "Monster", "isOpponent", MonsterFunctions::luaMonsterIsOpponent); + Lua::registerMethod(L, "Monster", "isFriend", MonsterFunctions::luaMonsterIsFriend); + Lua::registerMethod(L, "Monster", "addFriend", MonsterFunctions::luaMonsterAddFriend); + Lua::registerMethod(L, "Monster", "removeFriend", MonsterFunctions::luaMonsterRemoveFriend); + Lua::registerMethod(L, "Monster", "getFriendList", MonsterFunctions::luaMonsterGetFriendList); + Lua::registerMethod(L, "Monster", "getFriendCount", MonsterFunctions::luaMonsterGetFriendCount); + Lua::registerMethod(L, "Monster", "addTarget", MonsterFunctions::luaMonsterAddTarget); + Lua::registerMethod(L, "Monster", "removeTarget", MonsterFunctions::luaMonsterRemoveTarget); + Lua::registerMethod(L, "Monster", "getTargetList", MonsterFunctions::luaMonsterGetTargetList); + Lua::registerMethod(L, "Monster", "getTargetCount", MonsterFunctions::luaMonsterGetTargetCount); + Lua::registerMethod(L, "Monster", "changeTargetDistance", MonsterFunctions::luaMonsterChangeTargetDistance); + Lua::registerMethod(L, "Monster", "isChallenged", MonsterFunctions::luaMonsterIsChallenged); + Lua::registerMethod(L, "Monster", "selectTarget", MonsterFunctions::luaMonsterSelectTarget); + Lua::registerMethod(L, "Monster", "searchTarget", MonsterFunctions::luaMonsterSearchTarget); + Lua::registerMethod(L, "Monster", "setSpawnPosition", MonsterFunctions::luaMonsterSetSpawnPosition); + Lua::registerMethod(L, "Monster", "getRespawnType", MonsterFunctions::luaMonsterGetRespawnType); + + Lua::registerMethod(L, "Monster", "getTimeToChangeFiendish", MonsterFunctions::luaMonsterGetTimeToChangeFiendish); + Lua::registerMethod(L, "Monster", "setTimeToChangeFiendish", MonsterFunctions::luaMonsterSetTimeToChangeFiendish); + Lua::registerMethod(L, "Monster", "getMonsterForgeClassification", MonsterFunctions::luaMonsterGetMonsterForgeClassification); + Lua::registerMethod(L, "Monster", "setMonsterForgeClassification", MonsterFunctions::luaMonsterSetMonsterForgeClassification); + Lua::registerMethod(L, "Monster", "getForgeStack", MonsterFunctions::luaMonsterGetForgeStack); + Lua::registerMethod(L, "Monster", "setForgeStack", MonsterFunctions::luaMonsterSetForgeStack); + Lua::registerMethod(L, "Monster", "configureForgeSystem", MonsterFunctions::luaMonsterConfigureForgeSystem); + Lua::registerMethod(L, "Monster", "clearFiendishStatus", MonsterFunctions::luaMonsterClearFiendishStatus); + Lua::registerMethod(L, "Monster", "isForgeable", MonsterFunctions::luaMonsterIsForgeable); + + Lua::registerMethod(L, "Monster", "getName", MonsterFunctions::luaMonsterGetName); + Lua::registerMethod(L, "Monster", "setName", MonsterFunctions::luaMonsterSetName); + + Lua::registerMethod(L, "Monster", "hazard", MonsterFunctions::luaMonsterHazard); + Lua::registerMethod(L, "Monster", "hazardCrit", MonsterFunctions::luaMonsterHazardCrit); + Lua::registerMethod(L, "Monster", "hazardDodge", MonsterFunctions::luaMonsterHazardDodge); + Lua::registerMethod(L, "Monster", "hazardDamageBoost", MonsterFunctions::luaMonsterHazardDamageBoost); + Lua::registerMethod(L, "Monster", "hazardDefenseBoost", MonsterFunctions::luaMonsterHazardDefenseBoost); + + Lua::registerMethod(L, "Monster", "addReflectElement", MonsterFunctions::luaMonsterAddReflectElement); + Lua::registerMethod(L, "Monster", "addDefense", MonsterFunctions::luaMonsterAddDefense); + Lua::registerMethod(L, "Monster", "getDefense", MonsterFunctions::luaMonsterGetDefense); + + Lua::registerMethod(L, "Monster", "isDead", MonsterFunctions::luaMonsterIsDead); + Lua::registerMethod(L, "Monster", "immune", MonsterFunctions::luaMonsterImmune); + + CharmFunctions::init(L); + LootFunctions::init(L); + MonsterSpellFunctions::init(L); + MonsterTypeFunctions::init(L); +} int MonsterFunctions::luaMonsterCreate(lua_State* L) { // Monster(id or userdata) std::shared_ptr<Monster> monster; - if (isNumber(L, 2)) { - monster = g_game().getMonsterByID(getNumber<uint32_t>(L, 2)); - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_t::Monster) { + if (Lua::isNumber(L, 2)) { + monster = g_game().getMonsterByID(Lua::getNumber<uint32_t>(L, 2)); + } else if (Lua::isUserdata(L, 2)) { + if (Lua::getUserdataType(L, 2) != LuaData_t::Monster) { lua_pushnil(L); return 1; } - monster = getUserdataShared<Monster>(L, 2); + monster = Lua::getUserdataShared<Monster>(L, 2); } else { monster = nullptr; } if (monster) { - pushUserdata<Monster>(L, monster); - setMetatable(L, -1, "Monster"); + Lua::pushUserdata<Monster>(L, monster); + Lua::setMetatable(L, -1, "Monster"); } else { lua_pushnil(L); } @@ -41,16 +105,16 @@ int MonsterFunctions::luaMonsterCreate(lua_State* L) { int MonsterFunctions::luaMonsterIsMonster(lua_State* L) { // monster:isMonster() - pushBoolean(L, getUserdataShared<Monster>(L, 1) != nullptr); + Lua::pushBoolean(L, Lua::getUserdataShared<Monster>(L, 1) != nullptr); return 1; } int MonsterFunctions::luaMonsterGetType(lua_State* L) { // monster:getType() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - pushUserdata<MonsterType>(L, monster->mType); - setMetatable(L, -1, "MonsterType"); + Lua::pushUserdata<MonsterType>(L, monster->mType); + Lua::setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } @@ -59,14 +123,14 @@ int MonsterFunctions::luaMonsterGetType(lua_State* L) { int MonsterFunctions::luaMonsterSetType(lua_State* L) { // monster:setType(name or raceid, restoreHealth = false) - bool restoreHealth = getBoolean(L, 3, false); - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + bool restoreHealth = Lua::getBoolean(L, 3, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<MonsterType> mType = nullptr; - if (isNumber(L, 2)) { - mType = g_monsters().getMonsterTypeByRaceId(getNumber<uint16_t>(L, 2)); + std::shared_ptr<MonsterType> mType; + if (Lua::isNumber(L, 2)) { + mType = g_monsters().getMonsterTypeByRaceId(Lua::getNumber<uint16_t>(L, 2)); } else { - mType = g_monsters().getMonsterType(getString(L, 2)); + mType = g_monsters().getMonsterType(Lua::getString(L, 2)); } // Unregister creature events (current MonsterType) for (const std::string &scriptName : monster->mType->info.scripts) { @@ -102,7 +166,7 @@ int MonsterFunctions::luaMonsterSetType(lua_State* L) { for (const auto &spectator : Spectators().find<Player>(monster->getPosition(), true)) { spectator->getPlayer()->sendCreatureReload(monster); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -111,9 +175,9 @@ int MonsterFunctions::luaMonsterSetType(lua_State* L) { int MonsterFunctions::luaMonsterGetSpawnPosition(lua_State* L) { // monster:getSpawnPosition() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - pushPosition(L, monster->getMasterPos()); + Lua::pushPosition(L, monster->getMasterPos()); } else { lua_pushnil(L); } @@ -122,9 +186,9 @@ int MonsterFunctions::luaMonsterGetSpawnPosition(lua_State* L) { int MonsterFunctions::luaMonsterIsInSpawnRange(lua_State* L) { // monster:isInSpawnRange([position]) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - pushBoolean(L, monster->isInSpawnRange(lua_gettop(L) >= 2 ? getPosition(L, 2) : monster->getPosition())); + Lua::pushBoolean(L, monster->isInSpawnRange(lua_gettop(L) >= 2 ? Lua::getPosition(L, 2) : monster->getPosition())); } else { lua_pushnil(L); } @@ -133,9 +197,9 @@ int MonsterFunctions::luaMonsterIsInSpawnRange(lua_State* L) { int MonsterFunctions::luaMonsterIsIdle(lua_State* L) { // monster:isIdle() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - pushBoolean(L, monster->getIdleStatus()); + Lua::pushBoolean(L, monster->getIdleStatus()); } else { lua_pushnil(L); } @@ -144,23 +208,23 @@ int MonsterFunctions::luaMonsterIsIdle(lua_State* L) { int MonsterFunctions::luaMonsterSetIdle(lua_State* L) { // monster:setIdle(idle) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - monster->setIdle(getBoolean(L, 2)); - pushBoolean(L, true); + monster->setIdle(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterIsTarget(lua_State* L) { // monster:isTarget(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); - pushBoolean(L, monster->isTarget(creature)); + const auto &creature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, monster->isTarget(creature)); } else { lua_pushnil(L); } @@ -169,10 +233,10 @@ int MonsterFunctions::luaMonsterIsTarget(lua_State* L) { int MonsterFunctions::luaMonsterIsOpponent(lua_State* L) { // monster:isOpponent(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); - pushBoolean(L, monster->isOpponent(creature)); + const auto &creature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, monster->isOpponent(creature)); } else { lua_pushnil(L); } @@ -181,10 +245,10 @@ int MonsterFunctions::luaMonsterIsOpponent(lua_State* L) { int MonsterFunctions::luaMonsterIsFriend(lua_State* L) { // monster:isFriend(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); - pushBoolean(L, monster->isFriend(creature)); + const auto &creature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, monster->isFriend(creature)); } else { lua_pushnil(L); } @@ -193,11 +257,11 @@ int MonsterFunctions::luaMonsterIsFriend(lua_State* L) { int MonsterFunctions::luaMonsterAddFriend(lua_State* L) { // monster:addFriend(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &creature = Lua::getCreature(L, 2); monster->addFriend(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -206,11 +270,11 @@ int MonsterFunctions::luaMonsterAddFriend(lua_State* L) { int MonsterFunctions::luaMonsterRemoveFriend(lua_State* L) { // monster:removeFriend(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &creature = Lua::getCreature(L, 2); monster->removeFriend(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -219,7 +283,7 @@ int MonsterFunctions::luaMonsterRemoveFriend(lua_State* L) { int MonsterFunctions::luaMonsterGetFriendList(lua_State* L) { // monster:getFriendList() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; @@ -230,8 +294,8 @@ int MonsterFunctions::luaMonsterGetFriendList(lua_State* L) { int index = 0; for (const auto &creature : friendList) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; @@ -239,7 +303,7 @@ int MonsterFunctions::luaMonsterGetFriendList(lua_State* L) { int MonsterFunctions::luaMonsterGetFriendCount(lua_State* L) { // monster:getFriendCount() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { lua_pushnumber(L, monster->getFriendList().size()); } else { @@ -250,47 +314,47 @@ int MonsterFunctions::luaMonsterGetFriendCount(lua_State* L) { int MonsterFunctions::luaMonsterAddTarget(lua_State* L) { // monster:addTarget(creature[, pushFront = false]) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = getCreature(L, 2); - bool pushFront = getBoolean(L, 3, false); + const auto &creature = Lua::getCreature(L, 2); + const bool pushFront = Lua::getBoolean(L, 3, false); monster->addTarget(creature, pushFront); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterRemoveTarget(lua_State* L) { // monster:removeTarget(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - monster->removeTarget(getCreature(L, 2)); - pushBoolean(L, true); + monster->removeTarget(Lua::getCreature(L, 2)); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterGetTargetList(lua_State* L) { // monster:getTargetList() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - const auto targetList = monster->getTargetList(); + const auto &targetList = monster->getTargetList(); lua_createtable(L, targetList.size(), 0); int index = 0; - for (std::shared_ptr<Creature> creature : targetList) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + for (const auto &creature : targetList) { + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; @@ -298,7 +362,7 @@ int MonsterFunctions::luaMonsterGetTargetList(lua_State* L) { int MonsterFunctions::luaMonsterGetTargetCount(lua_State* L) { // monster:getTargetCount() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { lua_pushnumber(L, monster->getTargetList().size()); } else { @@ -309,11 +373,11 @@ int MonsterFunctions::luaMonsterGetTargetCount(lua_State* L) { int MonsterFunctions::luaMonsterChangeTargetDistance(lua_State* L) { // monster:changeTargetDistance(distance[, duration = 12000]) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - int32_t distance = getNumber<int32_t>(L, 2, 1); - uint32_t duration = getNumber<uint32_t>(L, 3, 12000); - pushBoolean(L, monster->changeTargetDistance(distance, duration)); + const auto distance = Lua::getNumber<int32_t>(L, 2, 1); + const auto duration = Lua::getNumber<uint32_t>(L, 3, 12000); + Lua::pushBoolean(L, monster->changeTargetDistance(distance, duration)); } else { lua_pushnil(L); } @@ -322,9 +386,9 @@ int MonsterFunctions::luaMonsterChangeTargetDistance(lua_State* L) { int MonsterFunctions::luaMonsterIsChallenged(lua_State* L) { // monster:isChallenged() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - pushBoolean(L, monster->isChallenged()); + Lua::pushBoolean(L, monster->isChallenged()); } else { lua_pushnil(L); } @@ -333,10 +397,10 @@ int MonsterFunctions::luaMonsterIsChallenged(lua_State* L) { int MonsterFunctions::luaMonsterSelectTarget(lua_State* L) { // monster:selectTarget(creature) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - std::shared_ptr<Creature> creature = getCreature(L, 2); - pushBoolean(L, monster->selectTarget(creature)); + const auto &creature = Lua::getCreature(L, 2); + Lua::pushBoolean(L, monster->selectTarget(creature)); } else { lua_pushnil(L); } @@ -345,10 +409,10 @@ int MonsterFunctions::luaMonsterSelectTarget(lua_State* L) { int MonsterFunctions::luaMonsterSearchTarget(lua_State* L) { // monster:searchTarget([searchType = TARGETSEARCH_DEFAULT]) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (monster) { - TargetSearchType_t searchType = getNumber<TargetSearchType_t>(L, 2, TARGETSEARCH_DEFAULT); - pushBoolean(L, monster->searchTarget(searchType)); + const auto &searchType = Lua::getNumber<TargetSearchType_t>(L, 2, TARGETSEARCH_DEFAULT); + Lua::pushBoolean(L, monster->searchTarget(searchType)); } else { lua_pushnil(L); } @@ -357,48 +421,48 @@ int MonsterFunctions::luaMonsterSearchTarget(lua_State* L) { int MonsterFunctions::luaMonsterSetSpawnPosition(lua_State* L) { // monster:setSpawnPosition(interval) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - uint32_t eventschedule = g_eventsScheduler().getSpawnMonsterSchedule(); + const uint32_t eventschedule = g_eventsScheduler().getSpawnMonsterSchedule(); const Position &pos = monster->getPosition(); monster->setMasterPos(pos); - SpawnMonster &spawnMonster = g_game().map.spawnsMonster.getspawnMonsterList().emplace_back(pos, 5); - uint32_t interval = getNumber<uint32_t>(L, 2, 90) * 1000 * 100 / std::max((uint32_t)1, (g_configManager().getNumber(RATE_SPAWN) * eventschedule)); - spawnMonster.addMonster(monster->mType->typeName, pos, DIRECTION_NORTH, static_cast<uint32_t>(interval)); - spawnMonster.startSpawnMonsterCheck(); + const auto &spawnMonster = g_game().map.spawnsMonster.getspawnMonsterList().emplace_back(std::make_shared<SpawnMonster>(pos, 5)); + uint32_t interval = Lua::getNumber<uint32_t>(L, 2, 90) * 1000 * 100 / std::max((uint32_t)1, (g_configManager().getNumber(RATE_SPAWN) * eventschedule)); + spawnMonster->addMonster(monster->mType->typeName, pos, DIRECTION_NORTH, static_cast<uint32_t>(interval)); + spawnMonster->startSpawnMonsterCheck(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterGetRespawnType(lua_State* L) { // monster:getRespawnType() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { lua_pushnil(L); return 1; } - RespawnType respawnType = monster->getRespawnType(); + const RespawnType respawnType = monster->getRespawnType(); lua_pushnumber(L, respawnType.period); - pushBoolean(L, respawnType.underground); + Lua::pushBoolean(L, respawnType.underground); return 2; } int MonsterFunctions::luaMonsterGetTimeToChangeFiendish(lua_State* L) { // monster:getTimeToChangeFiendish() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -408,11 +472,11 @@ int MonsterFunctions::luaMonsterGetTimeToChangeFiendish(lua_State* L) { int MonsterFunctions::luaMonsterSetTimeToChangeFiendish(lua_State* L) { // monster:setTimeToChangeFiendish(endTime) - time_t endTime = getNumber<uint32_t>(L, 2, 1); - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const time_t endTime = Lua::getNumber<uint32_t>(L, 2, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -422,25 +486,25 @@ int MonsterFunctions::luaMonsterSetTimeToChangeFiendish(lua_State* L) { int MonsterFunctions::luaMonsterGetMonsterForgeClassification(lua_State* L) { // monster:getMonsterForgeClassification() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - auto classification = static_cast<lua_Number>(monster->getMonsterForgeClassification()); + const auto classification = static_cast<lua_Number>(monster->getMonsterForgeClassification()); lua_pushnumber(L, classification); return 1; } int MonsterFunctions::luaMonsterSetMonsterForgeClassification(lua_State* L) { // monster:setMonsterForgeClassification(classication) - ForgeClassifications_t classification = getNumber<ForgeClassifications_t>(L, 2); - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const ForgeClassifications_t classification = Lua::getNumber<ForgeClassifications_t>(L, 2); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -450,10 +514,10 @@ int MonsterFunctions::luaMonsterSetMonsterForgeClassification(lua_State* L) { int MonsterFunctions::luaMonsterGetForgeStack(lua_State* L) { // monster:getForgeStack() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -463,16 +527,16 @@ int MonsterFunctions::luaMonsterGetForgeStack(lua_State* L) { int MonsterFunctions::luaMonsterSetForgeStack(lua_State* L) { // monster:setForgeStack(stack) - uint16_t stack = getNumber<uint16_t>(L, 2, 0); - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto stack = Lua::getNumber<uint16_t>(L, 2, 0); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } monster->setForgeStack(stack); - auto icon = stack < 15 + const auto icon = stack < 15 ? CreatureIconModifications_t::Influenced : CreatureIconModifications_t::Fiendish; monster->setIcon("forge", CreatureIcon(icon, icon == CreatureIconModifications_t::Influenced ? static_cast<uint8_t>(stack) : 0)); @@ -483,10 +547,10 @@ int MonsterFunctions::luaMonsterSetForgeStack(lua_State* L) { int MonsterFunctions::luaMonsterConfigureForgeSystem(lua_State* L) { // monster:configureForgeSystem() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -496,10 +560,10 @@ int MonsterFunctions::luaMonsterConfigureForgeSystem(lua_State* L) { int MonsterFunctions::luaMonsterClearFiendishStatus(lua_State* L) { // monster:clearFiendishStatus() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -509,58 +573,58 @@ int MonsterFunctions::luaMonsterClearFiendishStatus(lua_State* L) { int MonsterFunctions::luaMonsterIsForgeable(lua_State* L) { // monster:isForgeable() - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushBoolean(L, monster->canBeForgeMonster()); + Lua::pushBoolean(L, monster->canBeForgeMonster()); return 1; } int MonsterFunctions::luaMonsterGetName(lua_State* L) { // monster:getName() - const auto monster = getUserdataShared<Monster>(L, 1); + const auto monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushString(L, monster->getName()); + Lua::pushString(L, monster->getName()); return 1; } int MonsterFunctions::luaMonsterSetName(lua_State* L) { // monster:setName(name[, nameDescription]) - auto monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - monster->setName(getString(L, 2)); + monster->setName(Lua::getString(L, 2)); if (lua_gettop(L) >= 3) { - monster->setNameDescription(getString(L, 3)); + monster->setNameDescription(Lua::getString(L, 3)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterHazard(lua_State* L) { // get: monster:hazard() ; set: monster:hazard(hazard) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); - bool hazard = getBoolean(L, 2, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); + const bool hazard = Lua::getBoolean(L, 2, false); if (monster) { if (lua_gettop(L) == 1) { - pushBoolean(L, monster->getHazard()); + Lua::pushBoolean(L, monster->getHazard()); } else { monster->setHazard(hazard); - pushBoolean(L, monster->getHazard()); + Lua::pushBoolean(L, monster->getHazard()); } } else { lua_pushnil(L); @@ -570,14 +634,14 @@ int MonsterFunctions::luaMonsterHazard(lua_State* L) { int MonsterFunctions::luaMonsterHazardCrit(lua_State* L) { // get: monster:hazardCrit() ; set: monster:hazardCrit(hazardCrit) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); - bool hazardCrit = getBoolean(L, 2, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); + const bool hazardCrit = Lua::getBoolean(L, 2, false); if (monster) { if (lua_gettop(L) == 1) { - pushBoolean(L, monster->getHazardSystemCrit()); + Lua::pushBoolean(L, monster->getHazardSystemCrit()); } else { monster->setHazardSystemCrit(hazardCrit); - pushBoolean(L, monster->getHazardSystemCrit()); + Lua::pushBoolean(L, monster->getHazardSystemCrit()); } } else { lua_pushnil(L); @@ -587,14 +651,14 @@ int MonsterFunctions::luaMonsterHazardCrit(lua_State* L) { int MonsterFunctions::luaMonsterHazardDodge(lua_State* L) { // get: monster:hazardDodge() ; set: monster:hazardDodge(hazardDodge) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); - bool hazardDodge = getBoolean(L, 2, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); + const bool hazardDodge = Lua::getBoolean(L, 2, false); if (monster) { if (lua_gettop(L) == 1) { - pushBoolean(L, monster->getHazardSystemDodge()); + Lua::pushBoolean(L, monster->getHazardSystemDodge()); } else { monster->setHazardSystemDodge(hazardDodge); - pushBoolean(L, monster->getHazardSystemDodge()); + Lua::pushBoolean(L, monster->getHazardSystemDodge()); } } else { lua_pushnil(L); @@ -604,14 +668,14 @@ int MonsterFunctions::luaMonsterHazardDodge(lua_State* L) { int MonsterFunctions::luaMonsterHazardDamageBoost(lua_State* L) { // get: monster:hazardDamageBoost() ; set: monster:hazardDamageBoost(hazardDamageBoost) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); - bool hazardDamageBoost = getBoolean(L, 2, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); + const bool hazardDamageBoost = Lua::getBoolean(L, 2, false); if (monster) { if (lua_gettop(L) == 1) { - pushBoolean(L, monster->getHazardSystemDamageBoost()); + Lua::pushBoolean(L, monster->getHazardSystemDamageBoost()); } else { monster->setHazardSystemDamageBoost(hazardDamageBoost); - pushBoolean(L, monster->getHazardSystemDamageBoost()); + Lua::pushBoolean(L, monster->getHazardSystemDamageBoost()); } } else { lua_pushnil(L); @@ -621,14 +685,14 @@ int MonsterFunctions::luaMonsterHazardDamageBoost(lua_State* L) { int MonsterFunctions::luaMonsterHazardDefenseBoost(lua_State* L) { // get: monster:hazardDefenseBoost() ; set: monster:hazardDefenseBoost(hazardDefenseBoost) - std::shared_ptr<Monster> monster = getUserdataShared<Monster>(L, 1); - bool hazardDefenseBoost = getBoolean(L, 2, false); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); + const bool hazardDefenseBoost = Lua::getBoolean(L, 2, false); if (monster) { if (lua_gettop(L) == 1) { - pushBoolean(L, monster->getHazardSystemDefenseBoost()); + Lua::pushBoolean(L, monster->getHazardSystemDefenseBoost()); } else { monster->setHazardSystemDefenseBoost(hazardDefenseBoost); - pushBoolean(L, monster->getHazardSystemDefenseBoost()); + Lua::pushBoolean(L, monster->getHazardSystemDefenseBoost()); } } else { lua_pushnil(L); @@ -638,39 +702,39 @@ int MonsterFunctions::luaMonsterHazardDefenseBoost(lua_State* L) { int MonsterFunctions::luaMonsterAddReflectElement(lua_State* L) { // monster:addReflectElement(type, percent) - const auto &monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - CombatType_t element = getNumber<CombatType_t>(L, 2); - monster->addReflectElement(element, getNumber<int32_t>(L, 3)); - pushBoolean(L, true); + CombatType_t element = Lua::getNumber<CombatType_t>(L, 2); + monster->addReflectElement(element, Lua::getNumber<int32_t>(L, 3)); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterAddDefense(lua_State* L) { // monster:addDefense(defense) - const auto &monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - monster->addDefense(getNumber<int32_t>(L, 2)); - pushBoolean(L, true); + monster->addDefense(Lua::getNumber<int32_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int MonsterFunctions::luaMonsterGetDefense(lua_State* L) { // monster:getDefense(defense) - const auto &monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -680,31 +744,31 @@ int MonsterFunctions::luaMonsterGetDefense(lua_State* L) { int MonsterFunctions::luaMonsterIsDead(lua_State* L) { // monster:isDead() - const auto &monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushBoolean(L, monster->isDead()); + Lua::pushBoolean(L, monster->isDead()); return 1; } int MonsterFunctions::luaMonsterImmune(lua_State* L) { // to get: isImmune = monster:immune() // to set and get: newImmuneBool = monster:immune(newImmuneBool) - const auto &monster = getUserdataShared<Monster>(L, 1); + const auto &monster = Lua::getUserdataShared<Monster>(L, 1); if (!monster) { - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } if (lua_gettop(L) > 1) { - monster->setImmune(getBoolean(L, 2)); + monster->setImmune(Lua::getBoolean(L, 2)); } - pushBoolean(L, monster->isImmune()); + Lua::pushBoolean(L, monster->isImmune()); return 1; } diff --git a/src/lua/functions/creatures/monster/monster_functions.hpp b/src/lua/functions/creatures/monster/monster_functions.hpp index 90f2b526ca4..4ba696e941b 100644 --- a/src/lua/functions/creatures/monster/monster_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_functions.hpp @@ -9,73 +9,14 @@ #pragma once -#include "lua/scripts/luascript.hpp" #include "lua/functions/creatures/monster/charm_functions.hpp" #include "lua/functions/creatures/monster/loot_functions.hpp" #include "lua/functions/creatures/monster/monster_spell_functions.hpp" #include "lua/functions/creatures/monster/monster_type_functions.hpp" -class MonsterFunctions final : LuaScriptInterface { +class MonsterFunctions { private: - static void init(lua_State* L) { - registerSharedClass(L, "Monster", "Creature", MonsterFunctions::luaMonsterCreate); - registerMetaMethod(L, "Monster", "__eq", MonsterFunctions::luaUserdataCompare); - registerMethod(L, "Monster", "isMonster", MonsterFunctions::luaMonsterIsMonster); - registerMethod(L, "Monster", "getType", MonsterFunctions::luaMonsterGetType); - registerMethod(L, "Monster", "setType", MonsterFunctions::luaMonsterSetType); - registerMethod(L, "Monster", "getSpawnPosition", MonsterFunctions::luaMonsterGetSpawnPosition); - registerMethod(L, "Monster", "isInSpawnRange", MonsterFunctions::luaMonsterIsInSpawnRange); - registerMethod(L, "Monster", "isIdle", MonsterFunctions::luaMonsterIsIdle); - registerMethod(L, "Monster", "setIdle", MonsterFunctions::luaMonsterSetIdle); - registerMethod(L, "Monster", "isTarget", MonsterFunctions::luaMonsterIsTarget); - registerMethod(L, "Monster", "isOpponent", MonsterFunctions::luaMonsterIsOpponent); - registerMethod(L, "Monster", "isFriend", MonsterFunctions::luaMonsterIsFriend); - registerMethod(L, "Monster", "addFriend", MonsterFunctions::luaMonsterAddFriend); - registerMethod(L, "Monster", "removeFriend", MonsterFunctions::luaMonsterRemoveFriend); - registerMethod(L, "Monster", "getFriendList", MonsterFunctions::luaMonsterGetFriendList); - registerMethod(L, "Monster", "getFriendCount", MonsterFunctions::luaMonsterGetFriendCount); - registerMethod(L, "Monster", "addTarget", MonsterFunctions::luaMonsterAddTarget); - registerMethod(L, "Monster", "removeTarget", MonsterFunctions::luaMonsterRemoveTarget); - registerMethod(L, "Monster", "getTargetList", MonsterFunctions::luaMonsterGetTargetList); - registerMethod(L, "Monster", "getTargetCount", MonsterFunctions::luaMonsterGetTargetCount); - registerMethod(L, "Monster", "changeTargetDistance", MonsterFunctions::luaMonsterChangeTargetDistance); - registerMethod(L, "Monster", "isChallenged", MonsterFunctions::luaMonsterIsChallenged); - registerMethod(L, "Monster", "selectTarget", MonsterFunctions::luaMonsterSelectTarget); - registerMethod(L, "Monster", "searchTarget", MonsterFunctions::luaMonsterSearchTarget); - registerMethod(L, "Monster", "setSpawnPosition", MonsterFunctions::luaMonsterSetSpawnPosition); - registerMethod(L, "Monster", "getRespawnType", MonsterFunctions::luaMonsterGetRespawnType); - - registerMethod(L, "Monster", "getTimeToChangeFiendish", MonsterFunctions::luaMonsterGetTimeToChangeFiendish); - registerMethod(L, "Monster", "setTimeToChangeFiendish", MonsterFunctions::luaMonsterSetTimeToChangeFiendish); - registerMethod(L, "Monster", "getMonsterForgeClassification", MonsterFunctions::luaMonsterGetMonsterForgeClassification); - registerMethod(L, "Monster", "setMonsterForgeClassification", MonsterFunctions::luaMonsterSetMonsterForgeClassification); - registerMethod(L, "Monster", "getForgeStack", MonsterFunctions::luaMonsterGetForgeStack); - registerMethod(L, "Monster", "setForgeStack", MonsterFunctions::luaMonsterSetForgeStack); - registerMethod(L, "Monster", "configureForgeSystem", MonsterFunctions::luaMonsterConfigureForgeSystem); - registerMethod(L, "Monster", "clearFiendishStatus", MonsterFunctions::luaMonsterClearFiendishStatus); - registerMethod(L, "Monster", "isForgeable", MonsterFunctions::luaMonsterIsForgeable); - - registerMethod(L, "Monster", "getName", MonsterFunctions::luaMonsterGetName); - registerMethod(L, "Monster", "setName", MonsterFunctions::luaMonsterSetName); - - registerMethod(L, "Monster", "hazard", MonsterFunctions::luaMonsterHazard); - registerMethod(L, "Monster", "hazardCrit", MonsterFunctions::luaMonsterHazardCrit); - registerMethod(L, "Monster", "hazardDodge", MonsterFunctions::luaMonsterHazardDodge); - registerMethod(L, "Monster", "hazardDamageBoost", MonsterFunctions::luaMonsterHazardDamageBoost); - registerMethod(L, "Monster", "hazardDefenseBoost", MonsterFunctions::luaMonsterHazardDefenseBoost); - - registerMethod(L, "Monster", "addReflectElement", MonsterFunctions::luaMonsterAddReflectElement); - registerMethod(L, "Monster", "addDefense", MonsterFunctions::luaMonsterAddDefense); - registerMethod(L, "Monster", "getDefense", MonsterFunctions::luaMonsterGetDefense); - - registerMethod(L, "Monster", "isDead", MonsterFunctions::luaMonsterIsDead); - registerMethod(L, "Monster", "immune", MonsterFunctions::luaMonsterImmune); - - CharmFunctions::init(L); - LootFunctions::init(L); - MonsterSpellFunctions::init(L); - MonsterTypeFunctions::init(L); - } + static void init(lua_State* L); static int luaMonsterCreate(lua_State* L); diff --git a/src/lua/functions/creatures/monster/monster_spell_functions.cpp b/src/lua/functions/creatures/monster/monster_spell_functions.cpp index e9beb607bfc..9fec549c3dd 100644 --- a/src/lua/functions/creatures/monster/monster_spell_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_spell_functions.cpp @@ -8,21 +8,51 @@ */ #include "lua/functions/creatures/monster/monster_spell_functions.hpp" + #include "creatures/monsters/monsters.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void MonsterSpellFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "MonsterSpell", "", MonsterSpellFunctions::luaCreateMonsterSpell); + + Lua::registerMethod(L, "MonsterSpell", "setType", MonsterSpellFunctions::luaMonsterSpellSetType); + Lua::registerMethod(L, "MonsterSpell", "setScriptName", MonsterSpellFunctions::luaMonsterSpellSetScriptName); + Lua::registerMethod(L, "MonsterSpell", "setChance", MonsterSpellFunctions::luaMonsterSpellSetChance); + Lua::registerMethod(L, "MonsterSpell", "setInterval", MonsterSpellFunctions::luaMonsterSpellSetInterval); + Lua::registerMethod(L, "MonsterSpell", "setRange", MonsterSpellFunctions::luaMonsterSpellSetRange); + Lua::registerMethod(L, "MonsterSpell", "setCombatValue", MonsterSpellFunctions::luaMonsterSpellSetCombatValue); + Lua::registerMethod(L, "MonsterSpell", "setCombatType", MonsterSpellFunctions::luaMonsterSpellSetCombatType); + Lua::registerMethod(L, "MonsterSpell", "setAttackValue", MonsterSpellFunctions::luaMonsterSpellSetAttackValue); + Lua::registerMethod(L, "MonsterSpell", "setNeedTarget", MonsterSpellFunctions::luaMonsterSpellSetNeedTarget); + Lua::registerMethod(L, "MonsterSpell", "setCombatLength", MonsterSpellFunctions::luaMonsterSpellSetCombatLength); + Lua::registerMethod(L, "MonsterSpell", "setCombatSpread", MonsterSpellFunctions::luaMonsterSpellSetCombatSpread); + Lua::registerMethod(L, "MonsterSpell", "setCombatRadius", MonsterSpellFunctions::luaMonsterSpellSetCombatRadius); + Lua::registerMethod(L, "MonsterSpell", "setConditionType", MonsterSpellFunctions::luaMonsterSpellSetConditionType); + Lua::registerMethod(L, "MonsterSpell", "setConditionDamage", MonsterSpellFunctions::luaMonsterSpellSetConditionDamage); + Lua::registerMethod(L, "MonsterSpell", "setConditionSpeedChange", MonsterSpellFunctions::luaMonsterSpellSetConditionSpeedChange); + Lua::registerMethod(L, "MonsterSpell", "setConditionDuration", MonsterSpellFunctions::luaMonsterSpellSetConditionDuration); + Lua::registerMethod(L, "MonsterSpell", "setConditionTickInterval", MonsterSpellFunctions::luaMonsterSpellSetConditionTickInterval); + Lua::registerMethod(L, "MonsterSpell", "setCombatShootEffect", MonsterSpellFunctions::luaMonsterSpellSetCombatShootEffect); + Lua::registerMethod(L, "MonsterSpell", "setCombatEffect", MonsterSpellFunctions::luaMonsterSpellSetCombatEffect); + Lua::registerMethod(L, "MonsterSpell", "setOutfitMonster", MonsterSpellFunctions::luaMonsterSpellSetOutfitMonster); + Lua::registerMethod(L, "MonsterSpell", "setOutfitItem", MonsterSpellFunctions::luaMonsterSpellSetOutfitItem); + Lua::registerMethod(L, "MonsterSpell", "castSound", MonsterSpellFunctions::luaMonsterSpellCastSound); + Lua::registerMethod(L, "MonsterSpell", "impactSound", MonsterSpellFunctions::luaMonsterSpellImpactSound); +} int MonsterSpellFunctions::luaCreateMonsterSpell(lua_State* L) { const auto spell = std::make_shared<MonsterSpell>(); - pushUserdata<MonsterSpell>(L, spell); - setMetatable(L, -1, "MonsterSpell"); + Lua::pushUserdata<MonsterSpell>(L, spell); + Lua::setMetatable(L, -1, "MonsterSpell"); return 1; } int MonsterSpellFunctions::luaMonsterSpellSetType(lua_State* L) { // monsterSpell:setType(type) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->name = getString(L, 2); - pushBoolean(L, true); + spell->name = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -31,10 +61,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetType(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetScriptName(lua_State* L) { // monsterSpell:setScriptName(name) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->scriptName = getString(L, 2); - pushBoolean(L, true); + spell->scriptName = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -43,10 +73,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetScriptName(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetChance(lua_State* L) { // monsterSpell:setChance(chance) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->chance = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + spell->chance = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -55,10 +85,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetChance(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetInterval(lua_State* L) { // monsterSpell:setInterval(interval) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->interval = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + spell->interval = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -67,10 +97,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetInterval(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetRange(lua_State* L) { // monsterSpell:setRange(range) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->range = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + spell->range = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -79,11 +109,11 @@ int MonsterSpellFunctions::luaMonsterSpellSetRange(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatValue(lua_State* L) { // monsterSpell:setCombatValue(min, max) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->minCombatValue = getNumber<int32_t>(L, 2); - spell->maxCombatValue = getNumber<int32_t>(L, 3); - pushBoolean(L, true); + spell->minCombatValue = Lua::getNumber<int32_t>(L, 2); + spell->maxCombatValue = Lua::getNumber<int32_t>(L, 3); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -92,10 +122,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatValue(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatType(lua_State* L) { // monsterSpell:setCombatType(combatType_t) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->combatType = getNumber<CombatType_t>(L, 2); - pushBoolean(L, true); + spell->combatType = Lua::getNumber<CombatType_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -104,11 +134,11 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatType(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetAttackValue(lua_State* L) { // monsterSpell:setAttackValue(attack, skill) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->attack = getNumber<int32_t>(L, 2); - spell->skill = getNumber<int32_t>(L, 3); - pushBoolean(L, true); + spell->attack = Lua::getNumber<int32_t>(L, 2); + spell->skill = Lua::getNumber<int32_t>(L, 3); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -117,10 +147,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetAttackValue(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetNeedTarget(lua_State* L) { // monsterSpell:setNeedTarget(bool) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->needTarget = getBoolean(L, 2); - pushBoolean(L, true); + spell->needTarget = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -129,10 +159,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetNeedTarget(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatLength(lua_State* L) { // monsterSpell:setCombatLength(length) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->length = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->length = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -141,10 +171,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatLength(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatSpread(lua_State* L) { // monsterSpell:setCombatSpread(spread) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->spread = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->spread = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -153,10 +183,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatSpread(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatRadius(lua_State* L) { // monsterSpell:setCombatRadius(radius) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->radius = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->radius = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -165,18 +195,18 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatRadius(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetConditionType(lua_State* L) { // monsterSpell:setConditionType(type) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - auto conditionType = getNumber<uint8_t>(L, 2); + auto conditionType = Lua::getNumber<uint8_t>(L, 2); if (conditionType == 254) { g_logger().error("[{}] trying to register condition type none for monster: {}", __FUNCTION__, spell->name); - reportErrorFunc(fmt::format("trying to register condition type none for monster: {}", spell->name)); - pushBoolean(L, false); + Lua::reportErrorFunc(fmt::format("trying to register condition type none for monster: {}", spell->name)); + Lua::pushBoolean(L, false); return 1; } spell->conditionType = static_cast<ConditionType_t>(conditionType); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -185,12 +215,12 @@ int MonsterSpellFunctions::luaMonsterSpellSetConditionType(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetConditionDamage(lua_State* L) { // monsterSpell:setConditionDamage(min, max, start) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->conditionMinDamage = getNumber<int32_t>(L, 2); - spell->conditionMaxDamage = getNumber<int32_t>(L, 3); - spell->conditionStartDamage = getNumber<int32_t>(L, 4); - pushBoolean(L, true); + spell->conditionMinDamage = Lua::getNumber<int32_t>(L, 2); + spell->conditionMaxDamage = Lua::getNumber<int32_t>(L, 3); + spell->conditionStartDamage = Lua::getNumber<int32_t>(L, 4); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -199,10 +229,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetConditionDamage(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetConditionSpeedChange(lua_State* L) { // monsterSpell:setConditionSpeedChange(speed) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->speedChange = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->speedChange = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -211,10 +241,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetConditionSpeedChange(lua_State* L) int MonsterSpellFunctions::luaMonsterSpellSetConditionDuration(lua_State* L) { // monsterSpell:setConditionDuration(duration) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->duration = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->duration = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -223,10 +253,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetConditionDuration(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetConditionTickInterval(lua_State* L) { // monsterSpell:setConditionTickInterval(interval) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->tickInterval = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + spell->tickInterval = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -235,10 +265,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetConditionTickInterval(lua_State* L) int MonsterSpellFunctions::luaMonsterSpellSetCombatShootEffect(lua_State* L) { // monsterSpell:setCombatShootEffect(effect) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->shoot = getNumber<ShootType_t>(L, 2); - pushBoolean(L, true); + spell->shoot = Lua::getNumber<ShootType_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -247,10 +277,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatShootEffect(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetCombatEffect(lua_State* L) { // monsterSpell:setCombatEffect(effect) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->effect = getNumber<MagicEffectClasses>(L, 2); - pushBoolean(L, true); + spell->effect = Lua::getNumber<MagicEffectClasses>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -259,10 +289,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetCombatEffect(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetOutfitMonster(lua_State* L) { // monsterSpell:setOutfitMonster(effect) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->outfitMonster = getString(L, 2); - pushBoolean(L, true); + spell->outfitMonster = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -271,10 +301,10 @@ int MonsterSpellFunctions::luaMonsterSpellSetOutfitMonster(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellSetOutfitItem(lua_State* L) { // monsterSpell:setOutfitItem(effect) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (spell) { - spell->outfitItem = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + spell->outfitItem = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -283,24 +313,24 @@ int MonsterSpellFunctions::luaMonsterSpellSetOutfitItem(lua_State* L) { int MonsterSpellFunctions::luaMonsterSpellCastSound(lua_State* L) { // get: monsterSpell:castSound() set: monsterSpell:castSound(sound) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<lua_Number>(spell->soundCastEffect)); } else { - spell->soundCastEffect = getNumber<SoundEffect_t>(L, 2); - pushBoolean(L, true); + spell->soundCastEffect = Lua::getNumber<SoundEffect_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int MonsterSpellFunctions::luaMonsterSpellImpactSound(lua_State* L) { // get: monsterSpell:impactSound() set: monsterSpell:impactSound(sound) - const auto spell = getUserdataShared<MonsterSpell>(L, 1); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 1); if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<lua_Number>(spell->soundImpactEffect)); } else { - spell->soundImpactEffect = getNumber<SoundEffect_t>(L, 2); - pushBoolean(L, true); + spell->soundImpactEffect = Lua::getNumber<SoundEffect_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } diff --git a/src/lua/functions/creatures/monster/monster_spell_functions.hpp b/src/lua/functions/creatures/monster/monster_spell_functions.hpp index ad737ea9326..4816e899d9a 100644 --- a/src/lua/functions/creatures/monster/monster_spell_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_spell_functions.hpp @@ -9,37 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class MonsterSpellFunctions final : LuaScriptInterface { +class MonsterSpellFunctions { public: - static void init(lua_State* L) { - registerClass(L, "MonsterSpell", "", MonsterSpellFunctions::luaCreateMonsterSpell); - - registerMethod(L, "MonsterSpell", "setType", MonsterSpellFunctions::luaMonsterSpellSetType); - registerMethod(L, "MonsterSpell", "setScriptName", MonsterSpellFunctions::luaMonsterSpellSetScriptName); - registerMethod(L, "MonsterSpell", "setChance", MonsterSpellFunctions::luaMonsterSpellSetChance); - registerMethod(L, "MonsterSpell", "setInterval", MonsterSpellFunctions::luaMonsterSpellSetInterval); - registerMethod(L, "MonsterSpell", "setRange", MonsterSpellFunctions::luaMonsterSpellSetRange); - registerMethod(L, "MonsterSpell", "setCombatValue", MonsterSpellFunctions::luaMonsterSpellSetCombatValue); - registerMethod(L, "MonsterSpell", "setCombatType", MonsterSpellFunctions::luaMonsterSpellSetCombatType); - registerMethod(L, "MonsterSpell", "setAttackValue", MonsterSpellFunctions::luaMonsterSpellSetAttackValue); - registerMethod(L, "MonsterSpell", "setNeedTarget", MonsterSpellFunctions::luaMonsterSpellSetNeedTarget); - registerMethod(L, "MonsterSpell", "setCombatLength", MonsterSpellFunctions::luaMonsterSpellSetCombatLength); - registerMethod(L, "MonsterSpell", "setCombatSpread", MonsterSpellFunctions::luaMonsterSpellSetCombatSpread); - registerMethod(L, "MonsterSpell", "setCombatRadius", MonsterSpellFunctions::luaMonsterSpellSetCombatRadius); - registerMethod(L, "MonsterSpell", "setConditionType", MonsterSpellFunctions::luaMonsterSpellSetConditionType); - registerMethod(L, "MonsterSpell", "setConditionDamage", MonsterSpellFunctions::luaMonsterSpellSetConditionDamage); - registerMethod(L, "MonsterSpell", "setConditionSpeedChange", MonsterSpellFunctions::luaMonsterSpellSetConditionSpeedChange); - registerMethod(L, "MonsterSpell", "setConditionDuration", MonsterSpellFunctions::luaMonsterSpellSetConditionDuration); - registerMethod(L, "MonsterSpell", "setConditionTickInterval", MonsterSpellFunctions::luaMonsterSpellSetConditionTickInterval); - registerMethod(L, "MonsterSpell", "setCombatShootEffect", MonsterSpellFunctions::luaMonsterSpellSetCombatShootEffect); - registerMethod(L, "MonsterSpell", "setCombatEffect", MonsterSpellFunctions::luaMonsterSpellSetCombatEffect); - registerMethod(L, "MonsterSpell", "setOutfitMonster", MonsterSpellFunctions::luaMonsterSpellSetOutfitMonster); - registerMethod(L, "MonsterSpell", "setOutfitItem", MonsterSpellFunctions::luaMonsterSpellSetOutfitItem); - registerMethod(L, "MonsterSpell", "castSound", MonsterSpellFunctions::luaMonsterSpellCastSound); - registerMethod(L, "MonsterSpell", "impactSound", MonsterSpellFunctions::luaMonsterSpellImpactSound); - } + static void init(lua_State* L); private: static int luaCreateMonsterSpell(lua_State* L); diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index 1881e98653c..07ce44b626c 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -7,13 +7,151 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" -#include "io/io_bosstiary.hpp" +#include "lua/functions/creatures/monster/monster_type_functions.hpp" + +#include "config/configmanager.hpp" #include "creatures/combat/spells.hpp" -#include "creatures/monsters/monsters.hpp" #include "creatures/monsters/monster.hpp" -#include "lua/functions/creatures/monster/monster_type_functions.hpp" +#include "creatures/monsters/monsters.hpp" +#include "game/game.hpp" +#include "io/io_bosstiary.hpp" #include "lua/scripts/scripts.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void MonsterTypeFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "MonsterType", "", MonsterTypeFunctions::luaMonsterTypeCreate); + Lua::registerMetaMethod(L, "MonsterType", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "MonsterType", "isAttackable", MonsterTypeFunctions::luaMonsterTypeIsAttackable); + Lua::registerMethod(L, "MonsterType", "isConvinceable", MonsterTypeFunctions::luaMonsterTypeIsConvinceable); + Lua::registerMethod(L, "MonsterType", "isSummonable", MonsterTypeFunctions::luaMonsterTypeIsSummonable); + Lua::registerMethod(L, "MonsterType", "isPreyable", MonsterTypeFunctions::luaMonsterTypeIsPreyable); + Lua::registerMethod(L, "MonsterType", "isPreyExclusive", MonsterTypeFunctions::luaMonsterTypeIsPreyExclusive); + Lua::registerMethod(L, "MonsterType", "isIllusionable", MonsterTypeFunctions::luaMonsterTypeIsIllusionable); + Lua::registerMethod(L, "MonsterType", "isHostile", MonsterTypeFunctions::luaMonsterTypeIsHostile); + Lua::registerMethod(L, "MonsterType", "isPushable", MonsterTypeFunctions::luaMonsterTypeIsPushable); + Lua::registerMethod(L, "MonsterType", "isHealthHidden", MonsterTypeFunctions::luaMonsterTypeIsHealthHidden); + Lua::registerMethod(L, "MonsterType", "isBlockable", MonsterTypeFunctions::luaMonsterTypeIsBlockable); + Lua::registerMethod(L, "MonsterType", "isForgeCreature", MonsterTypeFunctions::luaMonsterTypeIsForgeCreature); + + Lua::registerMethod(L, "MonsterType", "familiar", MonsterTypeFunctions::luaMonsterTypeFamiliar); + Lua::registerMethod(L, "MonsterType", "isRewardBoss", MonsterTypeFunctions::luaMonsterTypeIsRewardBoss); + + Lua::registerMethod(L, "MonsterType", "canSpawn", MonsterTypeFunctions::luaMonsterTypeCanSpawn); + + Lua::registerMethod(L, "MonsterType", "canPushItems", MonsterTypeFunctions::luaMonsterTypeCanPushItems); + Lua::registerMethod(L, "MonsterType", "canPushCreatures", MonsterTypeFunctions::luaMonsterTypeCanPushCreatures); + + Lua::registerMethod(L, "MonsterType", "critChance", MonsterTypeFunctions::luaMonsterTypeCritChance); + + Lua::registerMethod(L, "MonsterType", "name", MonsterTypeFunctions::luaMonsterTypeName); + + Lua::registerMethod(L, "MonsterType", "nameDescription", MonsterTypeFunctions::luaMonsterTypeNameDescription); + + Lua::registerMethod(L, "MonsterType", "getCorpseId", MonsterTypeFunctions::luaMonsterTypegetCorpseId); + + Lua::registerMethod(L, "MonsterType", "health", MonsterTypeFunctions::luaMonsterTypeHealth); + Lua::registerMethod(L, "MonsterType", "maxHealth", MonsterTypeFunctions::luaMonsterTypeMaxHealth); + Lua::registerMethod(L, "MonsterType", "runHealth", MonsterTypeFunctions::luaMonsterTypeRunHealth); + Lua::registerMethod(L, "MonsterType", "experience", MonsterTypeFunctions::luaMonsterTypeExperience); + + Lua::registerMethod(L, "MonsterType", "faction", MonsterTypeFunctions::luaMonsterTypeFaction); + Lua::registerMethod(L, "MonsterType", "enemyFactions", MonsterTypeFunctions::luaMonsterTypeEnemyFactions); + Lua::registerMethod(L, "MonsterType", "targetPreferPlayer", MonsterTypeFunctions::luaMonsterTypeTargetPreferPlayer); + Lua::registerMethod(L, "MonsterType", "targetPreferMaster", MonsterTypeFunctions::luaMonsterTypeTargetPreferMaster); + + Lua::registerMethod(L, "MonsterType", "raceId", MonsterTypeFunctions::luaMonsterTypeRaceid); + Lua::registerMethod(L, "MonsterType", "Bestiaryclass", MonsterTypeFunctions::luaMonsterTypeBestiaryclass); + Lua::registerMethod(L, "MonsterType", "BestiaryOccurrence", MonsterTypeFunctions::luaMonsterTypeBestiaryOccurrence); + Lua::registerMethod(L, "MonsterType", "BestiaryLocations", MonsterTypeFunctions::luaMonsterTypeBestiaryLocations); + Lua::registerMethod(L, "MonsterType", "BestiaryStars", MonsterTypeFunctions::luaMonsterTypeBestiaryStars); + Lua::registerMethod(L, "MonsterType", "BestiaryCharmsPoints", MonsterTypeFunctions::luaMonsterTypeBestiaryCharmsPoints); + Lua::registerMethod(L, "MonsterType", "BestiarySecondUnlock", MonsterTypeFunctions::luaMonsterTypeBestiarySecondUnlock); + Lua::registerMethod(L, "MonsterType", "BestiaryFirstUnlock", MonsterTypeFunctions::luaMonsterTypeBestiaryFirstUnlock); + Lua::registerMethod(L, "MonsterType", "BestiarytoKill", MonsterTypeFunctions::luaMonsterTypeBestiarytoKill); + Lua::registerMethod(L, "MonsterType", "Bestiaryrace", MonsterTypeFunctions::luaMonsterTypeBestiaryrace); + + Lua::registerMethod(L, "MonsterType", "combatImmunities", MonsterTypeFunctions::luaMonsterTypeCombatImmunities); + Lua::registerMethod(L, "MonsterType", "conditionImmunities", MonsterTypeFunctions::luaMonsterTypeConditionImmunities); + + Lua::registerMethod(L, "MonsterType", "getAttackList", MonsterTypeFunctions::luaMonsterTypeGetAttackList); + Lua::registerMethod(L, "MonsterType", "addAttack", MonsterTypeFunctions::luaMonsterTypeAddAttack); + + Lua::registerMethod(L, "MonsterType", "getDefenseList", MonsterTypeFunctions::luaMonsterTypeGetDefenseList); + Lua::registerMethod(L, "MonsterType", "addDefense", MonsterTypeFunctions::luaMonsterTypeAddDefense); + + Lua::registerMethod(L, "MonsterType", "getTypeName", MonsterTypeFunctions::luaMonsterTypeGetTypeName); + + Lua::registerMethod(L, "MonsterType", "getElementList", MonsterTypeFunctions::luaMonsterTypeGetElementList); + Lua::registerMethod(L, "MonsterType", "addElement", MonsterTypeFunctions::luaMonsterTypeAddElement); + + Lua::registerMethod(L, "MonsterType", "addReflect", MonsterTypeFunctions::luaMonsterTypeAddReflect); + Lua::registerMethod(L, "MonsterType", "addHealing", MonsterTypeFunctions::luaMonsterTypeAddHealing); + + Lua::registerMethod(L, "MonsterType", "getVoices", MonsterTypeFunctions::luaMonsterTypeGetVoices); + Lua::registerMethod(L, "MonsterType", "addVoice", MonsterTypeFunctions::luaMonsterTypeAddVoice); + + Lua::registerMethod(L, "MonsterType", "getLoot", MonsterTypeFunctions::luaMonsterTypeGetLoot); + Lua::registerMethod(L, "MonsterType", "addLoot", MonsterTypeFunctions::luaMonsterTypeAddLoot); + + Lua::registerMethod(L, "MonsterType", "getCreatureEvents", MonsterTypeFunctions::luaMonsterTypeGetCreatureEvents); + Lua::registerMethod(L, "MonsterType", "registerEvent", MonsterTypeFunctions::luaMonsterTypeRegisterEvent); + + Lua::registerMethod(L, "MonsterType", "eventType", MonsterTypeFunctions::luaMonsterTypeEventType); + Lua::registerMethod(L, "MonsterType", "onThink", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onAppear", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onDisappear", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onMove", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onSay", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onPlayerAttack", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + Lua::registerMethod(L, "MonsterType", "onSpawn", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); + + Lua::registerMethod(L, "MonsterType", "getSummonList", MonsterTypeFunctions::luaMonsterTypeGetSummonList); + Lua::registerMethod(L, "MonsterType", "addSummon", MonsterTypeFunctions::luaMonsterTypeAddSummon); + + Lua::registerMethod(L, "MonsterType", "maxSummons", MonsterTypeFunctions::luaMonsterTypeMaxSummons); + + Lua::registerMethod(L, "MonsterType", "armor", MonsterTypeFunctions::luaMonsterTypeArmor); + Lua::registerMethod(L, "MonsterType", "mitigation", MonsterTypeFunctions::luaMonsterTypeMitigation); + Lua::registerMethod(L, "MonsterType", "defense", MonsterTypeFunctions::luaMonsterTypeDefense); + Lua::registerMethod(L, "MonsterType", "outfit", MonsterTypeFunctions::luaMonsterTypeOutfit); + Lua::registerMethod(L, "MonsterType", "race", MonsterTypeFunctions::luaMonsterTypeRace); + Lua::registerMethod(L, "MonsterType", "corpseId", MonsterTypeFunctions::luaMonsterTypeCorpseId); + Lua::registerMethod(L, "MonsterType", "manaCost", MonsterTypeFunctions::luaMonsterTypeManaCost); + Lua::registerMethod(L, "MonsterType", "baseSpeed", MonsterTypeFunctions::luaMonsterTypeBaseSpeed); + Lua::registerMethod(L, "MonsterType", "light", MonsterTypeFunctions::luaMonsterTypeLight); + + Lua::registerMethod(L, "MonsterType", "staticAttackChance", MonsterTypeFunctions::luaMonsterTypeStaticAttackChance); + Lua::registerMethod(L, "MonsterType", "targetDistance", MonsterTypeFunctions::luaMonsterTypeTargetDistance); + Lua::registerMethod(L, "MonsterType", "yellChance", MonsterTypeFunctions::luaMonsterTypeYellChance); + Lua::registerMethod(L, "MonsterType", "yellSpeedTicks", MonsterTypeFunctions::luaMonsterTypeYellSpeedTicks); + Lua::registerMethod(L, "MonsterType", "changeTargetChance", MonsterTypeFunctions::luaMonsterTypeChangeTargetChance); + Lua::registerMethod(L, "MonsterType", "changeTargetSpeed", MonsterTypeFunctions::luaMonsterTypeChangeTargetSpeed); + + Lua::registerMethod(L, "MonsterType", "canWalkOnEnergy", MonsterTypeFunctions::luaMonsterTypeCanWalkOnEnergy); + Lua::registerMethod(L, "MonsterType", "canWalkOnFire", MonsterTypeFunctions::luaMonsterTypeCanWalkOnFire); + Lua::registerMethod(L, "MonsterType", "canWalkOnPoison", MonsterTypeFunctions::luaMonsterTypeCanWalkOnPoison); + + Lua::registerMethod(L, "MonsterType", "strategiesTargetNearest", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetNearest); + Lua::registerMethod(L, "MonsterType", "strategiesTargetHealth", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetHealth); + Lua::registerMethod(L, "MonsterType", "strategiesTargetDamage", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetDamage); + Lua::registerMethod(L, "MonsterType", "strategiesTargetRandom", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetRandom); + + Lua::registerMethod(L, "MonsterType", "respawnTypePeriod", MonsterTypeFunctions::luaMonsterTypeRespawnTypePeriod); + Lua::registerMethod(L, "MonsterType", "respawnTypeIsUnderground", MonsterTypeFunctions::luaMonsterTypeRespawnTypeIsUnderground); + + Lua::registerMethod(L, "MonsterType", "bossRace", MonsterTypeFunctions::luaMonsterTypeBossRace); + Lua::registerMethod(L, "MonsterType", "bossRaceId", MonsterTypeFunctions::luaMonsterTypeBossRaceId); + + Lua::registerMethod(L, "MonsterType", "soundChance", MonsterTypeFunctions::luaMonsterTypeSoundChance); + Lua::registerMethod(L, "MonsterType", "soundSpeedTicks", MonsterTypeFunctions::luaMonsterTypeSoundSpeedTicks); + Lua::registerMethod(L, "MonsterType", "addSound", MonsterTypeFunctions::luaMonsterTypeAddSound); + Lua::registerMethod(L, "MonsterType", "getSounds", MonsterTypeFunctions::luaMonsterTypeGetSounds); + Lua::registerMethod(L, "MonsterType", "deathSound", MonsterTypeFunctions::luaMonsterTypedeathSound); + + Lua::registerMethod(L, "MonsterType", "variant", MonsterTypeFunctions::luaMonsterTypeVariant); +} void MonsterTypeFunctions::createMonsterTypeLootLuaTable(lua_State* L, const std::vector<LootBlock> &lootList) { lua_createtable(L, lootList.size(), 0); @@ -22,14 +160,14 @@ void MonsterTypeFunctions::createMonsterTypeLootLuaTable(lua_State* L, const std for (const auto &lootBlock : lootList) { lua_createtable(L, 0, 8); - setField(L, "itemId", lootBlock.id); - setField(L, "chance", lootBlock.chance); - setField(L, "subType", lootBlock.subType); - setField(L, "maxCount", lootBlock.countmax); - setField(L, "minCount", lootBlock.countmin); - setField(L, "actionId", lootBlock.actionId); - setField(L, "text", lootBlock.text); - pushBoolean(L, lootBlock.unique); + Lua::setField(L, "itemId", lootBlock.id); + Lua::setField(L, "chance", lootBlock.chance); + Lua::setField(L, "subType", lootBlock.subType); + Lua::setField(L, "maxCount", lootBlock.countmax); + Lua::setField(L, "minCount", lootBlock.countmin); + Lua::setField(L, "actionId", lootBlock.actionId); + Lua::setField(L, "text", lootBlock.text); + Lua::pushBoolean(L, lootBlock.unique); lua_setfield(L, -2, "unique"); createMonsterTypeLootLuaTable(L, lootBlock.childLoot); @@ -41,16 +179,16 @@ void MonsterTypeFunctions::createMonsterTypeLootLuaTable(lua_State* L, const std int MonsterTypeFunctions::luaMonsterTypeCreate(lua_State* L) { // MonsterType(name or raceid) - std::shared_ptr<MonsterType> monsterType = nullptr; - if (isNumber(L, 2)) { - monsterType = g_monsters().getMonsterTypeByRaceId(getNumber<uint16_t>(L, 2)); + std::shared_ptr<MonsterType> monsterType; + if (Lua::isNumber(L, 2)) { + monsterType = g_monsters().getMonsterTypeByRaceId(Lua::getNumber<uint16_t>(L, 2)); } else { - monsterType = g_monsters().getMonsterType(getString(L, 2)); + monsterType = g_monsters().getMonsterType(Lua::getString(L, 2)); } if (monsterType) { - pushUserdata<MonsterType>(L, monsterType); - setMetatable(L, -1, "MonsterType"); + Lua::pushUserdata<MonsterType>(L, monsterType); + Lua::setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } @@ -59,13 +197,13 @@ int MonsterTypeFunctions::luaMonsterTypeCreate(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsAttackable(lua_State* L) { // get: monsterType:isAttackable() set: monsterType:isAttackable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isAttackable); + Lua::pushBoolean(L, monsterType->info.isAttackable); } else { - monsterType->info.isAttackable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isAttackable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -75,13 +213,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsAttackable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsConvinceable(lua_State* L) { // get: monsterType:isConvinceable() set: monsterType:isConvinceable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isConvinceable); + Lua::pushBoolean(L, monsterType->info.isConvinceable); } else { - monsterType->info.isConvinceable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isConvinceable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -91,13 +229,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsConvinceable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsSummonable(lua_State* L) { // get: monsterType:isSummonable() set: monsterType:isSummonable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isSummonable); + Lua::pushBoolean(L, monsterType->info.isSummonable); } else { - monsterType->info.isSummonable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isSummonable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -107,13 +245,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsSummonable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsPreyExclusive(lua_State* L) { // get: monsterType:isPreyExclusive() set: monsterType:isPreyExclusive(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isPreyExclusive); + Lua::pushBoolean(L, monsterType->info.isPreyExclusive); } else { - monsterType->info.isPreyExclusive = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isPreyExclusive = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -123,13 +261,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsPreyExclusive(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsPreyable(lua_State* L) { // get: monsterType:isPreyable() set: monsterType:isPreyable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isPreyable); + Lua::pushBoolean(L, monsterType->info.isPreyable); } else { - monsterType->info.isPreyable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isPreyable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -139,13 +277,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsPreyable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsIllusionable(lua_State* L) { // get: monsterType:isIllusionable() set: monsterType:isIllusionable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isIllusionable); + Lua::pushBoolean(L, monsterType->info.isIllusionable); } else { - monsterType->info.isIllusionable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isIllusionable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -155,13 +293,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsIllusionable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsHostile(lua_State* L) { // get: monsterType:isHostile() set: monsterType:isHostile(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isHostile); + Lua::pushBoolean(L, monsterType->info.isHostile); } else { - monsterType->info.isHostile = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isHostile = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -171,13 +309,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsHostile(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeFamiliar(lua_State* L) { // get: monsterType:familiar() set: monsterType:familiar(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isFamiliar); + Lua::pushBoolean(L, monsterType->info.isFamiliar); } else { - monsterType->info.isFamiliar = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isFamiliar = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -187,13 +325,13 @@ int MonsterTypeFunctions::luaMonsterTypeFamiliar(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsRewardBoss(lua_State* L) { // get: monsterType:isRewardBoss() set: monsterType:isRewardBoss(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isRewardBoss); + Lua::pushBoolean(L, monsterType->info.isRewardBoss); } else { - monsterType->info.isRewardBoss = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isRewardBoss = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -203,13 +341,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsRewardBoss(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsPushable(lua_State* L) { // get: monsterType:isPushable() set: monsterType:isPushable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.pushable); + Lua::pushBoolean(L, monsterType->info.pushable); } else { - monsterType->info.pushable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.pushable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -219,13 +357,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsPushable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsHealthHidden(lua_State* L) { // get: monsterType:isHealthHidden() set: monsterType:isHealthHidden(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.hiddenHealth); + Lua::pushBoolean(L, monsterType->info.hiddenHealth); } else { - monsterType->info.hiddenHealth = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.hiddenHealth = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -235,13 +373,13 @@ int MonsterTypeFunctions::luaMonsterTypeIsHealthHidden(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsBlockable(lua_State* L) { // get: monsterType:isBlockable() set: monsterType:isBlockable(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isBlockable); + Lua::pushBoolean(L, monsterType->info.isBlockable); } else { - monsterType->info.isBlockable = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isBlockable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -251,28 +389,28 @@ int MonsterTypeFunctions::luaMonsterTypeIsBlockable(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeIsForgeCreature(lua_State* L) { // get: monsterType:isForgeCreature() set: monsterType:isForgeCreature(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 0; } if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.isForgeCreature); + Lua::pushBoolean(L, monsterType->info.isForgeCreature); } else { - monsterType->info.isForgeCreature = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.isForgeCreature = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } return 1; } int MonsterTypeFunctions::luaMonsterTypeCanSpawn(lua_State* L) { // monsterType:canSpawn(pos) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); - const Position &position = getPosition(L, 2); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); + const Position &position = Lua::getPosition(L, 2); if (monsterType) { - pushBoolean(L, monsterType->canSpawn(position)); + Lua::pushBoolean(L, monsterType->canSpawn(position)); } else { lua_pushnil(L); } @@ -281,13 +419,13 @@ int MonsterTypeFunctions::luaMonsterTypeCanSpawn(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCanPushItems(lua_State* L) { // get: monsterType:canPushItems() set: monsterType:canPushItems(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.canPushItems); + Lua::pushBoolean(L, monsterType->info.canPushItems); } else { - monsterType->info.canPushItems = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.canPushItems = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -297,13 +435,13 @@ int MonsterTypeFunctions::luaMonsterTypeCanPushItems(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCanPushCreatures(lua_State* L) { // get: monsterType:canPushCreatures() set: monsterType:canPushCreatures(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.canPushCreatures); + Lua::pushBoolean(L, monsterType->info.canPushCreatures); } else { - monsterType->info.canPushCreatures = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.canPushCreatures = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -313,10 +451,10 @@ int MonsterTypeFunctions::luaMonsterTypeCanPushCreatures(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCritChance(lua_State* L) { // get: monsterType:critChance() set: monsterType:critChance(int) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 2) { - monsterType->info.critChance = getNumber<uint16_t>(L, 2); + monsterType->info.critChance = Lua::getNumber<uint16_t>(L, 2); } lua_pushnumber(L, monsterType->info.critChance); } else { @@ -327,13 +465,13 @@ int MonsterTypeFunctions::luaMonsterTypeCritChance(lua_State* L) { int32_t MonsterTypeFunctions::luaMonsterTypeName(lua_State* L) { // get: monsterType:name() set: monsterType:name(name) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushString(L, monsterType->name); + Lua::pushString(L, monsterType->name); } else { - monsterType->name = getString(L, 2); - pushBoolean(L, true); + monsterType->name = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -343,13 +481,13 @@ int32_t MonsterTypeFunctions::luaMonsterTypeName(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeNameDescription(lua_State* L) { // get: monsterType:nameDescription() set: monsterType:nameDescription(desc) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushString(L, monsterType->nameDescription); + Lua::pushString(L, monsterType->nameDescription); } else { - monsterType->nameDescription = getString(L, 2); - pushBoolean(L, true); + monsterType->nameDescription = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -359,7 +497,7 @@ int MonsterTypeFunctions::luaMonsterTypeNameDescription(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypegetCorpseId(lua_State* L) { // monsterType:getCorpseId() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.lookcorpse); } else { @@ -370,13 +508,13 @@ int MonsterTypeFunctions::luaMonsterTypegetCorpseId(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeHealth(lua_State* L) { // get: monsterType:health() set: monsterType:health(health) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.health); } else { - monsterType->info.health = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.health = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -386,13 +524,13 @@ int MonsterTypeFunctions::luaMonsterTypeHealth(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeMaxHealth(lua_State* L) { // get: monsterType:maxHealth() set: monsterType:maxHealth(health) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.healthMax); } else { - monsterType->info.healthMax = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.healthMax = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -402,13 +540,13 @@ int MonsterTypeFunctions::luaMonsterTypeMaxHealth(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRunHealth(lua_State* L) { // get: monsterType:runHealth() set: monsterType:runHealth(health) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.runAwayHealth); } else { - monsterType->info.runAwayHealth = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.runAwayHealth = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -418,13 +556,13 @@ int MonsterTypeFunctions::luaMonsterTypeRunHealth(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeExperience(lua_State* L) { // get: monsterType:experience() set: monsterType:experience(exp) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.experience); } else { - monsterType->info.experience = getNumber<uint64_t>(L, 2); - pushBoolean(L, true); + monsterType->info.experience = Lua::getNumber<uint64_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -434,13 +572,13 @@ int MonsterTypeFunctions::luaMonsterTypeExperience(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeFaction(lua_State* L) { // get: monsterType:faction() set: monsterType:faction(faction) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.faction); } else { - monsterType->info.faction = getNumber<Faction_t>(L, 2); - pushBoolean(L, true); + monsterType->info.faction = Lua::getNumber<Faction_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -450,7 +588,7 @@ int MonsterTypeFunctions::luaMonsterTypeFaction(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeEnemyFactions(lua_State* L) { // get: monsterType:enemyFactions() set: monsterType:enemyFactions(enemyFaction) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_createtable(L, monsterType->info.enemyFactions.size(), 0); @@ -461,9 +599,9 @@ int MonsterTypeFunctions::luaMonsterTypeEnemyFactions(lua_State* L) { lua_rawseti(L, -2, ++index); } } else { - Faction_t faction = getNumber<Faction_t>(L, 2); + const Faction_t faction = Lua::getNumber<Faction_t>(L, 2); monsterType->info.enemyFactions.insert(faction); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -473,13 +611,13 @@ int MonsterTypeFunctions::luaMonsterTypeEnemyFactions(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeTargetPreferPlayer(lua_State* L) { // get: monsterType:targetPreferPlayer() set: monsterType:targetPreferPlayer(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushboolean(L, monsterType->info.targetPreferPlayer); } else { - monsterType->info.targetPreferPlayer = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.targetPreferPlayer = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -489,13 +627,13 @@ int MonsterTypeFunctions::luaMonsterTypeTargetPreferPlayer(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeTargetPreferMaster(lua_State* L) { // get: monsterType:targetPreferMaster() set: monsterType:targetPreferMaster(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.faction); } else { - monsterType->info.targetPreferMaster = getBoolean(L, 2); - pushBoolean(L, true); + monsterType->info.targetPreferMaster = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -505,14 +643,14 @@ int MonsterTypeFunctions::luaMonsterTypeTargetPreferMaster(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRaceid(lua_State* L) { // get: monsterType:raceId() set: monsterType:raceId(id) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.raceid); } else { - monsterType->info.raceid = getNumber<uint16_t>(L, 2); - g_game().addBestiaryList(getNumber<uint16_t>(L, 2), monsterType->name); - pushBoolean(L, true); + monsterType->info.raceid = Lua::getNumber<uint16_t>(L, 2); + g_game().addBestiaryList(Lua::getNumber<uint16_t>(L, 2), monsterType->name); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -522,13 +660,13 @@ int MonsterTypeFunctions::luaMonsterTypeRaceid(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiarytoKill(lua_State* L) { // get: monsterType:BestiarytoKill() set: monsterType:BestiarytoKill(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryToUnlock); } else { - monsterType->info.bestiaryToUnlock = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryToUnlock = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -538,13 +676,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiarytoKill(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryFirstUnlock(lua_State* L) { // get: monsterType:BestiaryFirstUnlock() set: monsterType:BestiaryFirstUnlock(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryFirstUnlock); } else { - monsterType->info.bestiaryFirstUnlock = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryFirstUnlock = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -554,13 +692,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryFirstUnlock(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiarySecondUnlock(lua_State* L) { // get: monsterType:BestiarySecondUnlock() set: monsterType:BestiarySecondUnlock(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiarySecondUnlock); } else { - monsterType->info.bestiarySecondUnlock = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiarySecondUnlock = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -570,13 +708,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiarySecondUnlock(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryCharmsPoints(lua_State* L) { // get: monsterType:BestiaryCharmsPoints() set: monsterType:BestiaryCharmsPoints(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryCharmsPoints); } else { - monsterType->info.bestiaryCharmsPoints = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryCharmsPoints = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -586,13 +724,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryCharmsPoints(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryStars(lua_State* L) { // get: monsterType:BestiaryStars() set: monsterType:BestiaryStars(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryStars); } else { - monsterType->info.bestiaryStars = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryStars = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -602,13 +740,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryStars(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryOccurrence(lua_State* L) { // get: monsterType:BestiaryOccurrence() set: monsterType:BestiaryOccurrence(value) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryOccurrence); } else { - monsterType->info.bestiaryOccurrence = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryOccurrence = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -618,13 +756,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryOccurrence(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryLocations(lua_State* L) { // get: monsterType:BestiaryLocations() set: monsterType:BestiaryLocations(string) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushString(L, monsterType->info.bestiaryLocations); + Lua::pushString(L, monsterType->info.bestiaryLocations); } else { - monsterType->info.bestiaryLocations = getString(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryLocations = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -634,13 +772,13 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryLocations(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryclass(lua_State* L) { // get: monsterType:Bestiaryclass() set: monsterType:Bestiaryclass(string) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushString(L, monsterType->info.bestiaryClass); + Lua::pushString(L, monsterType->info.bestiaryClass); } else { - monsterType->info.bestiaryClass = getString(L, 2); - pushBoolean(L, true); + monsterType->info.bestiaryClass = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -650,14 +788,14 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryclass(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBestiaryrace(lua_State* L) { // get: monsterType:Bestiaryrace() set: monsterType:Bestiaryrace(raceid) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.bestiaryRace); } else { - BestiaryType_t race = getNumber<BestiaryType_t>(L, 2); + const BestiaryType_t race = Lua::getNumber<BestiaryType_t>(L, 2); monsterType->info.bestiaryRace = race; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -667,10 +805,10 @@ int MonsterTypeFunctions::luaMonsterTypeBestiaryrace(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCombatImmunities(lua_State* L) { // get: monsterType:combatImmunities() set: monsterType:combatImmunities(immunity) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 1; } @@ -683,7 +821,7 @@ int MonsterTypeFunctions::luaMonsterTypeCombatImmunities(lua_State* L) { return 1; } - std::string immunity = getString(L, 2); + std::string immunity = Lua::getString(L, 2); CombatType_t combatType = COMBAT_NONE; if (immunity == "physical") { combatType = COMBAT_PHYSICALDAMAGE; @@ -717,16 +855,16 @@ int MonsterTypeFunctions::luaMonsterTypeCombatImmunities(lua_State* L) { } monsterType->info.m_damageImmunities.set(combatTypeToIndex(combatType), true); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MonsterTypeFunctions::luaMonsterTypeConditionImmunities(lua_State* L) { // get: monsterType:conditionImmunities() set: monsterType:conditionImmunities(immunity) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 1; } @@ -739,7 +877,7 @@ int MonsterTypeFunctions::luaMonsterTypeConditionImmunities(lua_State* L) { return 1; } - std::string immunity = getString(L, 2); + std::string immunity = Lua::getString(L, 2); ConditionType_t conditionType = CONDITION_NONE; if (immunity == "physical") { conditionType = CONDITION_BLEEDING; @@ -775,13 +913,13 @@ int MonsterTypeFunctions::luaMonsterTypeConditionImmunities(lua_State* L) { } monsterType->info.m_conditionImmunities[static_cast<size_t>(conditionType)] = true; - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MonsterTypeFunctions::luaMonsterTypeGetAttackList(lua_State* L) { // monsterType:getAttackList() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -793,15 +931,15 @@ int MonsterTypeFunctions::luaMonsterTypeGetAttackList(lua_State* L) { for (const auto &spellBlock : monsterType->info.attackSpells) { lua_createtable(L, 0, 8); - setField(L, "chance", spellBlock.chance); - setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); - setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); - setField(L, "minCombatValue", spellBlock.minCombatValue); - setField(L, "maxCombatValue", spellBlock.maxCombatValue); - setField(L, "range", spellBlock.range); - setField(L, "speed", spellBlock.speed); + Lua::setField(L, "chance", spellBlock.chance); + Lua::setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); + Lua::setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); + Lua::setField(L, "minCombatValue", spellBlock.minCombatValue); + Lua::setField(L, "maxCombatValue", spellBlock.maxCombatValue); + Lua::setField(L, "range", spellBlock.range); + Lua::setField(L, "speed", spellBlock.speed); const auto combatSpell = std::static_pointer_cast<CombatSpell>(spellBlock.spell); - pushUserdata<CombatSpell>(L, combatSpell); + Lua::pushUserdata<CombatSpell>(L, combatSpell); lua_setfield(L, -2, "spell"); lua_rawseti(L, -2, ++index); @@ -811,9 +949,9 @@ int MonsterTypeFunctions::luaMonsterTypeGetAttackList(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddAttack(lua_State* L) { // monsterType:addAttack(monsterspell) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - const auto spell = getUserdataShared<MonsterSpell>(L, 2); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 2); if (spell) { spellBlock_t sb; if (g_monsters().deserializeSpell(spell, sb, monsterType->name)) { @@ -832,7 +970,7 @@ int MonsterTypeFunctions::luaMonsterTypeAddAttack(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetDefenseList(lua_State* L) { // monsterType:getDefenseList() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -844,15 +982,15 @@ int MonsterTypeFunctions::luaMonsterTypeGetDefenseList(lua_State* L) { for (const auto &spellBlock : monsterType->info.defenseSpells) { lua_createtable(L, 0, 8); - setField(L, "chance", spellBlock.chance); - setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); - setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); - setField(L, "minCombatValue", spellBlock.minCombatValue); - setField(L, "maxCombatValue", spellBlock.maxCombatValue); - setField(L, "range", spellBlock.range); - setField(L, "speed", spellBlock.speed); + Lua::setField(L, "chance", spellBlock.chance); + Lua::setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); + Lua::setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); + Lua::setField(L, "minCombatValue", spellBlock.minCombatValue); + Lua::setField(L, "maxCombatValue", spellBlock.maxCombatValue); + Lua::setField(L, "range", spellBlock.range); + Lua::setField(L, "speed", spellBlock.speed); const auto combatSpell = std::static_pointer_cast<CombatSpell>(spellBlock.spell); - pushUserdata<CombatSpell>(L, combatSpell); + Lua::pushUserdata<CombatSpell>(L, combatSpell); lua_setfield(L, -2, "spell"); lua_rawseti(L, -2, ++index); @@ -862,20 +1000,20 @@ int MonsterTypeFunctions::luaMonsterTypeGetDefenseList(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetTypeName(lua_State* L) { // monsterType:getTypeName() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { return 1; } - pushString(L, monsterType->typeName); + Lua::pushString(L, monsterType->typeName); return 1; } int MonsterTypeFunctions::luaMonsterTypeAddDefense(lua_State* L) { // monsterType:addDefense(monsterspell) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - const auto spell = getUserdataShared<MonsterSpell>(L, 2); + const auto &spell = Lua::getUserdataShared<MonsterSpell>(L, 2); if (spell) { spellBlock_t sb; if (g_monsters().deserializeSpell(spell, sb, monsterType->name)) { @@ -894,11 +1032,11 @@ int MonsterTypeFunctions::luaMonsterTypeAddDefense(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddElement(lua_State* L) { // monsterType:addElement(type, percent) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - CombatType_t element = getNumber<CombatType_t>(L, 2); - monsterType->info.elementMap[element] = getNumber<int32_t>(L, 3); - pushBoolean(L, true); + const CombatType_t element = Lua::getNumber<CombatType_t>(L, 2); + monsterType->info.elementMap[element] = Lua::getNumber<int32_t>(L, 3); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -907,11 +1045,11 @@ int MonsterTypeFunctions::luaMonsterTypeAddElement(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddReflect(lua_State* L) { // monsterType:addReflect(type, percent) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - CombatType_t element = getNumber<CombatType_t>(L, 2); - monsterType->info.reflectMap[element] = getNumber<int32_t>(L, 3); - pushBoolean(L, true); + const CombatType_t element = Lua::getNumber<CombatType_t>(L, 2); + monsterType->info.reflectMap[element] = Lua::getNumber<int32_t>(L, 3); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -920,11 +1058,11 @@ int MonsterTypeFunctions::luaMonsterTypeAddReflect(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddHealing(lua_State* L) { // monsterType:addHealing(type, percent) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - CombatType_t element = getNumber<CombatType_t>(L, 2); - monsterType->info.healingMap[element] = getNumber<int32_t>(L, 3); - pushBoolean(L, true); + const CombatType_t element = Lua::getNumber<CombatType_t>(L, 2); + monsterType->info.healingMap[element] = Lua::getNumber<int32_t>(L, 3); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -933,7 +1071,7 @@ int MonsterTypeFunctions::luaMonsterTypeAddHealing(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetElementList(lua_State* L) { // monsterType:getElementList() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -949,15 +1087,15 @@ int MonsterTypeFunctions::luaMonsterTypeGetElementList(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddVoice(lua_State* L) { // monsterType:addVoice(sentence, interval, chance, yell) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { voiceBlock_t voice; - voice.text = getString(L, 2); - monsterType->info.yellSpeedTicks = getNumber<uint32_t>(L, 3); - monsterType->info.yellChance = getNumber<uint32_t>(L, 4); - voice.yellText = getBoolean(L, 5); + voice.text = Lua::getString(L, 2); + monsterType->info.yellSpeedTicks = Lua::getNumber<uint32_t>(L, 3); + monsterType->info.yellChance = Lua::getNumber<uint32_t>(L, 4); + voice.yellText = Lua::getBoolean(L, 5); monsterType->info.voiceVector.push_back(voice); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -966,7 +1104,7 @@ int MonsterTypeFunctions::luaMonsterTypeAddVoice(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetVoices(lua_State* L) { // monsterType:getVoices() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -976,8 +1114,8 @@ int MonsterTypeFunctions::luaMonsterTypeGetVoices(lua_State* L) { lua_createtable(L, monsterType->info.voiceVector.size(), 0); for (const auto &voiceBlock : monsterType->info.voiceVector) { lua_createtable(L, 0, 2); - setField(L, "text", voiceBlock.text); - setField(L, "yellText", voiceBlock.yellText); + Lua::setField(L, "text", voiceBlock.text); + Lua::setField(L, "yellText", voiceBlock.yellText); lua_rawseti(L, -2, ++index); } return 1; @@ -985,7 +1123,7 @@ int MonsterTypeFunctions::luaMonsterTypeGetVoices(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetLoot(lua_State* L) { // monsterType:getLoot() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -997,12 +1135,12 @@ int MonsterTypeFunctions::luaMonsterTypeGetLoot(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddLoot(lua_State* L) { // monsterType:addLoot(loot) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - const auto loot = getUserdataShared<Loot>(L, 2); + const auto &loot = Lua::getUserdataShared<Loot>(L, 2); if (loot) { monsterType->loadLoot(monsterType, loot->lootBlock); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1014,7 +1152,7 @@ int MonsterTypeFunctions::luaMonsterTypeAddLoot(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetCreatureEvents(lua_State* L) { // monsterType:getCreatureEvents() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -1023,7 +1161,7 @@ int MonsterTypeFunctions::luaMonsterTypeGetCreatureEvents(lua_State* L) { int index = 0; lua_createtable(L, monsterType->info.scripts.size(), 0); for (const std::string &creatureEvent : monsterType->info.scripts) { - pushString(L, creatureEvent); + Lua::pushString(L, creatureEvent); lua_rawseti(L, -2, ++index); } return 1; @@ -1031,16 +1169,16 @@ int MonsterTypeFunctions::luaMonsterTypeGetCreatureEvents(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRegisterEvent(lua_State* L) { // monsterType:registerEvent(name) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { - auto eventName = getString(L, 2); + const auto eventName = Lua::getString(L, 2); monsterType->info.scripts.insert(eventName); for (const auto &[_, monster] : g_game().getMonsters()) { if (monster->getMonsterType() == monsterType) { monster->registerCreatureEvent(eventName); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1055,13 +1193,13 @@ int MonsterTypeFunctions::luaMonsterTypeEventOnCallback(lua_State* L) { // monsterType:onSay(callback) // monsterType:onPlayerAttack(callback) // monsterType:onSpawn(callback) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (monsterType->loadCallback(&g_scripts().getScriptInterface())) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } - pushBoolean(L, false); + Lua::pushBoolean(L, false); } else { lua_pushnil(L); } @@ -1070,10 +1208,10 @@ int MonsterTypeFunctions::luaMonsterTypeEventOnCallback(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeEventType(lua_State* L) { // monstertype:eventType(event) - const auto mType = getUserdataShared<MonsterType>(L, 1); + const auto &mType = Lua::getUserdataShared<MonsterType>(L, 1); if (mType) { - mType->info.eventType = getNumber<MonstersEvent_t>(L, 2); - pushBoolean(L, true); + mType->info.eventType = Lua::getNumber<MonstersEvent_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1082,7 +1220,7 @@ int MonsterTypeFunctions::luaMonsterTypeEventType(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeGetSummonList(lua_State* L) { // monsterType:getSummonList() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -1092,9 +1230,9 @@ int MonsterTypeFunctions::luaMonsterTypeGetSummonList(lua_State* L) { lua_createtable(L, monsterType->info.summons.size(), 0); for (const auto &summonBlock : monsterType->info.summons) { lua_createtable(L, 0, 3); - setField(L, "name", summonBlock.name); - setField(L, "speed", summonBlock.speed); - setField(L, "chance", summonBlock.chance); + Lua::setField(L, "name", summonBlock.name); + Lua::setField(L, "speed", summonBlock.speed); + Lua::setField(L, "chance", summonBlock.chance); lua_rawseti(L, -2, ++index); } return 1; @@ -1102,15 +1240,15 @@ int MonsterTypeFunctions::luaMonsterTypeGetSummonList(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeAddSummon(lua_State* L) { // monsterType:addSummon(name, interval, chance[, count = 1]) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { summonBlock_t summon; - summon.name = getString(L, 2); - summon.speed = getNumber<int32_t>(L, 3); - summon.count = getNumber<int32_t>(L, 5, 1); - summon.chance = getNumber<int32_t>(L, 4); + summon.name = Lua::getString(L, 2); + summon.speed = Lua::getNumber<int32_t>(L, 3); + summon.count = Lua::getNumber<int32_t>(L, 5, 1); + summon.chance = Lua::getNumber<int32_t>(L, 4); monsterType->info.summons.push_back(summon); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1119,13 +1257,13 @@ int MonsterTypeFunctions::luaMonsterTypeAddSummon(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeMaxSummons(lua_State* L) { // get: monsterType:maxSummons() set: monsterType:maxSummons(ammount) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.maxSummons); } else { - monsterType->info.maxSummons = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.maxSummons = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1135,13 +1273,13 @@ int MonsterTypeFunctions::luaMonsterTypeMaxSummons(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeArmor(lua_State* L) { // get: monsterType:armor() set: monsterType:armor(armor) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.armor); } else { - monsterType->info.armor = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.armor = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1151,31 +1289,31 @@ int MonsterTypeFunctions::luaMonsterTypeArmor(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeMitigation(lua_State* L) { // get: monsterType:mitigation() set: monsterType:mitigation(mitigation) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.mitigation); } else { - monsterType->info.mitigation = getNumber<float>(L, 2); - pushBoolean(L, true); + monsterType->info.mitigation = Lua::getNumber<float>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int MonsterTypeFunctions::luaMonsterTypeDefense(lua_State* L) { // get: monsterType:defense() set: monsterType:defense(defense) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.defense); } else { - monsterType->info.defense = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.defense = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1185,18 +1323,18 @@ int MonsterTypeFunctions::luaMonsterTypeDefense(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeOutfit(lua_State* L) { // get: monsterType:outfit() set: monsterType:outfit(outfit) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushOutfit(L, monsterType->info.outfit); + Lua::pushOutfit(L, monsterType->info.outfit); } else { - Outfit_t outfit = getOutfit(L, 2); + Outfit_t outfit = Lua::getOutfit(L, 2); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && outfit.lookType != 0 && !g_game().isLookTypeRegistered(outfit.lookType)) { g_logger().warn("[MonsterTypeFunctions::luaMonsterTypeOutfit] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", outfit.lookType); lua_pushnil(L); } else { monsterType->info.outfit = outfit; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } } else { @@ -1207,8 +1345,8 @@ int MonsterTypeFunctions::luaMonsterTypeOutfit(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRace(lua_State* L) { // get: monsterType:race() set: monsterType:race(race) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); - std::string race = getString(L, 2); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); + std::string race = Lua::getString(L, 2); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.race); @@ -1232,7 +1370,7 @@ int MonsterTypeFunctions::luaMonsterTypeRace(lua_State* L) { lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1242,12 +1380,12 @@ int MonsterTypeFunctions::luaMonsterTypeRace(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCorpseId(lua_State* L) { // get: monsterType:corpseId() set: monsterType:corpseId(id) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.lookcorpse); } else { - monsterType->info.lookcorpse = getNumber<uint16_t>(L, 2); + monsterType->info.lookcorpse = Lua::getNumber<uint16_t>(L, 2); lua_pushboolean(L, true); } } else { @@ -1258,13 +1396,13 @@ int MonsterTypeFunctions::luaMonsterTypeCorpseId(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeManaCost(lua_State* L) { // get: monsterType:manaCost() set: monsterType:manaCost(mana) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.manaCost); } else { - monsterType->info.manaCost = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.manaCost = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1274,13 +1412,13 @@ int MonsterTypeFunctions::luaMonsterTypeManaCost(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBaseSpeed(lua_State* L) { // monsterType:baseSpeed() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->getBaseSpeed()); } else { - monsterType->setBaseSpeed(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + monsterType->setBaseSpeed(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1289,7 +1427,7 @@ int MonsterTypeFunctions::luaMonsterTypeBaseSpeed(lua_State* L) { } int MonsterTypeFunctions::luaMonsterTypeLight(lua_State* L) { // get: monsterType:light() set: monsterType:light(color, level) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -1300,22 +1438,22 @@ int MonsterTypeFunctions::luaMonsterTypeLight(lua_State* L) { lua_pushnumber(L, monsterType->info.light.color); return 2; } else { - monsterType->info.light.color = getNumber<uint8_t>(L, 2); - monsterType->info.light.level = getNumber<uint8_t>(L, 3); - pushBoolean(L, true); + monsterType->info.light.color = Lua::getNumber<uint8_t>(L, 2); + monsterType->info.light.level = Lua::getNumber<uint8_t>(L, 3); + Lua::pushBoolean(L, true); } return 1; } int MonsterTypeFunctions::luaMonsterTypeStaticAttackChance(lua_State* L) { // get: monsterType:staticAttackChance() set: monsterType:staticAttackChance(chance) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.staticAttackChance); } else { - monsterType->info.staticAttackChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.staticAttackChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1325,13 +1463,13 @@ int MonsterTypeFunctions::luaMonsterTypeStaticAttackChance(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeTargetDistance(lua_State* L) { // get: monsterType:targetDistance() set: monsterType:targetDistance(distance) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.targetDistance); } else { - monsterType->info.targetDistance = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.targetDistance = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1341,18 +1479,18 @@ int MonsterTypeFunctions::luaMonsterTypeTargetDistance(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeYellChance(lua_State* L) { // get: monsterType:yellChance() set: monsterType:yellChance(chance) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.yellChance); } else { - monsterType->info.yellChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.yellChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { - monsterType->info.yellChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.yellChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1362,13 +1500,13 @@ int MonsterTypeFunctions::luaMonsterTypeYellChance(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeYellSpeedTicks(lua_State* L) { // get: monsterType:yellSpeedTicks() set: monsterType:yellSpeedTicks(rate) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.yellSpeedTicks); } else { - monsterType->info.yellSpeedTicks = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.yellSpeedTicks = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1378,13 +1516,13 @@ int MonsterTypeFunctions::luaMonsterTypeYellSpeedTicks(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeChangeTargetChance(lua_State* L) { // monsterType:getChangeTargetChance() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.changeTargetChance); } else { - monsterType->info.changeTargetChance = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.changeTargetChance = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1394,13 +1532,13 @@ int MonsterTypeFunctions::luaMonsterTypeChangeTargetChance(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeChangeTargetSpeed(lua_State* L) { // get: monsterType:changeTargetSpeed() set: monsterType:changeTargetSpeed(speed) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.changeTargetSpeed); } else { - monsterType->info.changeTargetSpeed = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.changeTargetSpeed = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1410,13 +1548,13 @@ int MonsterTypeFunctions::luaMonsterTypeChangeTargetSpeed(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCanWalkOnEnergy(lua_State* L) { // get: monsterType:canWalkOnEnergy() set: monsterType:canWalkOnEnergy(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.canWalkOnEnergy); + Lua::pushBoolean(L, monsterType->info.canWalkOnEnergy); } else { - monsterType->info.canWalkOnEnergy = getBoolean(L, 2, true); - pushBoolean(L, true); + monsterType->info.canWalkOnEnergy = Lua::getBoolean(L, 2, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1426,13 +1564,13 @@ int MonsterTypeFunctions::luaMonsterTypeCanWalkOnEnergy(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCanWalkOnFire(lua_State* L) { // get: monsterType:canWalkOnFire() set: monsterType:canWalkOnFire(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.canWalkOnFire); + Lua::pushBoolean(L, monsterType->info.canWalkOnFire); } else { - monsterType->info.canWalkOnFire = getBoolean(L, 2, true); - pushBoolean(L, true); + monsterType->info.canWalkOnFire = Lua::getBoolean(L, 2, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1442,13 +1580,13 @@ int MonsterTypeFunctions::luaMonsterTypeCanWalkOnFire(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeCanWalkOnPoison(lua_State* L) { // get: monsterType:canWalkOnPoison() set: monsterType:canWalkOnPoison(bool) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { - pushBoolean(L, monsterType->info.canWalkOnPoison); + Lua::pushBoolean(L, monsterType->info.canWalkOnPoison); } else { - monsterType->info.canWalkOnPoison = getBoolean(L, 2, true); - pushBoolean(L, true); + monsterType->info.canWalkOnPoison = Lua::getBoolean(L, 2, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1458,13 +1596,13 @@ int MonsterTypeFunctions::luaMonsterTypeCanWalkOnPoison(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetNearest(lua_State* L) { // monsterType:strategiesTargetNearest() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.strategiesTargetNearest); } else { - monsterType->info.strategiesTargetNearest = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.strategiesTargetNearest = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1474,13 +1612,13 @@ int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetNearest(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetHealth(lua_State* L) { // monsterType:strategiesTargetHealth() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.strategiesTargetHealth); } else { - monsterType->info.strategiesTargetHealth = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.strategiesTargetHealth = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1490,13 +1628,13 @@ int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetHealth(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetDamage(lua_State* L) { // monsterType:strategiesTargetDamage() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.strategiesTargetDamage); } else { - monsterType->info.strategiesTargetDamage = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.strategiesTargetDamage = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1506,13 +1644,13 @@ int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetDamage(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetRandom(lua_State* L) { // monsterType:strategiesTargetRandom() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.strategiesTargetRandom); } else { - monsterType->info.strategiesTargetRandom = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.strategiesTargetRandom = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1526,13 +1664,13 @@ int MonsterTypeFunctions::luaMonsterTypeStrategiesTargetRandom(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRespawnTypePeriod(lua_State* L) { // monsterType:respawnTypePeriod() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.respawnType.period); } else { - monsterType->info.respawnType.period = getNumber<RespawnPeriod_t>(L, 2); - pushBoolean(L, true); + monsterType->info.respawnType.period = Lua::getNumber<RespawnPeriod_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1542,13 +1680,13 @@ int MonsterTypeFunctions::luaMonsterTypeRespawnTypePeriod(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeRespawnTypeIsUnderground(lua_State* L) { // monsterType:respawnTypeIsUnderground() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (monsterType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.respawnType.underground); } else { - monsterType->info.respawnType.underground = getNumber<RespawnPeriod_t>(L, 2); - pushBoolean(L, true); + monsterType->info.respawnType.underground = Lua::getNumber<RespawnPeriod_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -1559,10 +1697,10 @@ int MonsterTypeFunctions::luaMonsterTypeRespawnTypeIsUnderground(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBossRace(lua_State* L) { // set: monsterType:bosstiaryRace(raceId, class) // get: monsterType:bosstiaryRace() = this return only class name - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 0; } @@ -1571,13 +1709,13 @@ int MonsterTypeFunctions::luaMonsterTypeBossRace(lua_State* L) { lua_pushnil(L); return 1; } - pushString(L, monsterType->info.bosstiaryClass); + Lua::pushString(L, monsterType->info.bosstiaryClass); } else { - auto bossRace = getNumber<uint8_t>(L, 2, 0); - auto bossClass = getString(L, 3); + const auto bossRace = Lua::getNumber<uint8_t>(L, 2, 0); + const auto bossClass = Lua::getString(L, 3); monsterType->info.bosstiaryRace = magic_enum::enum_value<BosstiaryRarity_t>(bossRace); monsterType->info.bosstiaryClass = bossClass; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } return 1; @@ -1586,10 +1724,10 @@ int MonsterTypeFunctions::luaMonsterTypeBossRace(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeBossRaceId(lua_State* L) { // set: monsterType:bossRaceId(raceId) // get: monsterType:bossRaceId() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_MONSTER_TYPE_NOT_FOUND)); return 0; } @@ -1600,10 +1738,10 @@ int MonsterTypeFunctions::luaMonsterTypeBossRaceId(lua_State* L) { lua_pushnumber(L, static_cast<lua_Number>(monsterType->info.bosstiaryRace)); } } else { - auto raceId = getNumber<uint16_t>(L, 2, 0); + const auto raceId = Lua::getNumber<uint16_t>(L, 2, 0); monsterType->info.raceid = raceId; g_ioBosstiary().addBosstiaryMonster(raceId, monsterType->typeName); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } return 1; @@ -1611,57 +1749,57 @@ int MonsterTypeFunctions::luaMonsterTypeBossRaceId(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeSoundChance(lua_State* L) { // get: monsterType:soundChance() set: monsterType:soundChance(chance) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.soundChance); } else { - monsterType->info.soundChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.soundChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int MonsterTypeFunctions::luaMonsterTypeSoundSpeedTicks(lua_State* L) { // get: monsterType:soundSpeedTicks() set: monsterType:soundSpeedTicks(ticks) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, monsterType->info.soundSpeedTicks); } else { - monsterType->info.soundSpeedTicks = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + monsterType->info.soundSpeedTicks = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int MonsterTypeFunctions::luaMonsterTypeAddSound(lua_State* L) { // monsterType:addSound(soundId) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - monsterType->info.soundVector.push_back(getNumber<SoundEffect_t>(L, 2)); - pushBoolean(L, true); + monsterType->info.soundVector.push_back(Lua::getNumber<SoundEffect_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int MonsterTypeFunctions::luaMonsterTypeGetSounds(lua_State* L) { // monsterType:getSounds() - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { lua_pushnil(L); return 1; @@ -1680,18 +1818,18 @@ int MonsterTypeFunctions::luaMonsterTypeGetSounds(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypedeathSound(lua_State* L) { // get: monsterType:deathSound() set: monsterType:deathSound(sound) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, static_cast<lua_Number>(monsterType->info.deathSound)); } else { - monsterType->info.deathSound = getNumber<SoundEffect_t>(L, 2); - pushBoolean(L, true); + monsterType->info.deathSound = Lua::getNumber<SoundEffect_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; @@ -1699,18 +1837,18 @@ int MonsterTypeFunctions::luaMonsterTypedeathSound(lua_State* L) { int MonsterTypeFunctions::luaMonsterTypeVariant(lua_State* L) { // get: monsterType:variant() set: monsterType:variant(variantName) - const auto monsterType = getUserdataShared<MonsterType>(L, 1); + const auto &monsterType = Lua::getUserdataShared<MonsterType>(L, 1); if (!monsterType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { - pushString(L, monsterType->variantName); + Lua::pushString(L, monsterType->variantName); } else { - monsterType->variantName = getString(L, 2); - pushBoolean(L, true); + monsterType->variantName = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } return 1; diff --git a/src/lua/functions/creatures/monster/monster_type_functions.hpp b/src/lua/functions/creatures/monster/monster_type_functions.hpp index 6923740db41..e272ea45cd7 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.hpp @@ -9,143 +9,11 @@ #pragma once -#include "lua/scripts/luascript.hpp" +struct LootBlock; -class MonsterTypeFunctions final : LuaScriptInterface { +class MonsterTypeFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "MonsterType", "", MonsterTypeFunctions::luaMonsterTypeCreate); - registerMetaMethod(L, "MonsterType", "__eq", MonsterTypeFunctions::luaUserdataCompare); - - registerMethod(L, "MonsterType", "isAttackable", MonsterTypeFunctions::luaMonsterTypeIsAttackable); - registerMethod(L, "MonsterType", "isConvinceable", MonsterTypeFunctions::luaMonsterTypeIsConvinceable); - registerMethod(L, "MonsterType", "isSummonable", MonsterTypeFunctions::luaMonsterTypeIsSummonable); - registerMethod(L, "MonsterType", "isPreyable", MonsterTypeFunctions::luaMonsterTypeIsPreyable); - registerMethod(L, "MonsterType", "isPreyExclusive", MonsterTypeFunctions::luaMonsterTypeIsPreyExclusive); - registerMethod(L, "MonsterType", "isIllusionable", MonsterTypeFunctions::luaMonsterTypeIsIllusionable); - registerMethod(L, "MonsterType", "isHostile", MonsterTypeFunctions::luaMonsterTypeIsHostile); - registerMethod(L, "MonsterType", "isPushable", MonsterTypeFunctions::luaMonsterTypeIsPushable); - registerMethod(L, "MonsterType", "isHealthHidden", MonsterTypeFunctions::luaMonsterTypeIsHealthHidden); - registerMethod(L, "MonsterType", "isBlockable", MonsterTypeFunctions::luaMonsterTypeIsBlockable); - registerMethod(L, "MonsterType", "isForgeCreature", MonsterTypeFunctions::luaMonsterTypeIsForgeCreature); - - registerMethod(L, "MonsterType", "familiar", MonsterTypeFunctions::luaMonsterTypeFamiliar); - registerMethod(L, "MonsterType", "isRewardBoss", MonsterTypeFunctions::luaMonsterTypeIsRewardBoss); - - registerMethod(L, "MonsterType", "canSpawn", MonsterTypeFunctions::luaMonsterTypeCanSpawn); - - 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); - - registerMethod(L, "MonsterType", "getCorpseId", MonsterTypeFunctions::luaMonsterTypegetCorpseId); - - registerMethod(L, "MonsterType", "health", MonsterTypeFunctions::luaMonsterTypeHealth); - registerMethod(L, "MonsterType", "maxHealth", MonsterTypeFunctions::luaMonsterTypeMaxHealth); - registerMethod(L, "MonsterType", "runHealth", MonsterTypeFunctions::luaMonsterTypeRunHealth); - registerMethod(L, "MonsterType", "experience", MonsterTypeFunctions::luaMonsterTypeExperience); - - registerMethod(L, "MonsterType", "faction", MonsterTypeFunctions::luaMonsterTypeFaction); - registerMethod(L, "MonsterType", "enemyFactions", MonsterTypeFunctions::luaMonsterTypeEnemyFactions); - registerMethod(L, "MonsterType", "targetPreferPlayer", MonsterTypeFunctions::luaMonsterTypeTargetPreferPlayer); - registerMethod(L, "MonsterType", "targetPreferMaster", MonsterTypeFunctions::luaMonsterTypeTargetPreferMaster); - - registerMethod(L, "MonsterType", "raceId", MonsterTypeFunctions::luaMonsterTypeRaceid); - registerMethod(L, "MonsterType", "Bestiaryclass", MonsterTypeFunctions::luaMonsterTypeBestiaryclass); - registerMethod(L, "MonsterType", "BestiaryOccurrence", MonsterTypeFunctions::luaMonsterTypeBestiaryOccurrence); - registerMethod(L, "MonsterType", "BestiaryLocations", MonsterTypeFunctions::luaMonsterTypeBestiaryLocations); - registerMethod(L, "MonsterType", "BestiaryStars", MonsterTypeFunctions::luaMonsterTypeBestiaryStars); - registerMethod(L, "MonsterType", "BestiaryCharmsPoints", MonsterTypeFunctions::luaMonsterTypeBestiaryCharmsPoints); - registerMethod(L, "MonsterType", "BestiarySecondUnlock", MonsterTypeFunctions::luaMonsterTypeBestiarySecondUnlock); - registerMethod(L, "MonsterType", "BestiaryFirstUnlock", MonsterTypeFunctions::luaMonsterTypeBestiaryFirstUnlock); - registerMethod(L, "MonsterType", "BestiarytoKill", MonsterTypeFunctions::luaMonsterTypeBestiarytoKill); - registerMethod(L, "MonsterType", "Bestiaryrace", MonsterTypeFunctions::luaMonsterTypeBestiaryrace); - - registerMethod(L, "MonsterType", "combatImmunities", MonsterTypeFunctions::luaMonsterTypeCombatImmunities); - registerMethod(L, "MonsterType", "conditionImmunities", MonsterTypeFunctions::luaMonsterTypeConditionImmunities); - - registerMethod(L, "MonsterType", "getAttackList", MonsterTypeFunctions::luaMonsterTypeGetAttackList); - registerMethod(L, "MonsterType", "addAttack", MonsterTypeFunctions::luaMonsterTypeAddAttack); - - registerMethod(L, "MonsterType", "getDefenseList", MonsterTypeFunctions::luaMonsterTypeGetDefenseList); - registerMethod(L, "MonsterType", "addDefense", MonsterTypeFunctions::luaMonsterTypeAddDefense); - - registerMethod(L, "MonsterType", "getTypeName", MonsterTypeFunctions::luaMonsterTypeGetTypeName); - - registerMethod(L, "MonsterType", "getElementList", MonsterTypeFunctions::luaMonsterTypeGetElementList); - registerMethod(L, "MonsterType", "addElement", MonsterTypeFunctions::luaMonsterTypeAddElement); - - registerMethod(L, "MonsterType", "addReflect", MonsterTypeFunctions::luaMonsterTypeAddReflect); - registerMethod(L, "MonsterType", "addHealing", MonsterTypeFunctions::luaMonsterTypeAddHealing); - - registerMethod(L, "MonsterType", "getVoices", MonsterTypeFunctions::luaMonsterTypeGetVoices); - registerMethod(L, "MonsterType", "addVoice", MonsterTypeFunctions::luaMonsterTypeAddVoice); - - registerMethod(L, "MonsterType", "getLoot", MonsterTypeFunctions::luaMonsterTypeGetLoot); - registerMethod(L, "MonsterType", "addLoot", MonsterTypeFunctions::luaMonsterTypeAddLoot); - - registerMethod(L, "MonsterType", "getCreatureEvents", MonsterTypeFunctions::luaMonsterTypeGetCreatureEvents); - registerMethod(L, "MonsterType", "registerEvent", MonsterTypeFunctions::luaMonsterTypeRegisterEvent); - - registerMethod(L, "MonsterType", "eventType", MonsterTypeFunctions::luaMonsterTypeEventType); - registerMethod(L, "MonsterType", "onThink", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onAppear", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onDisappear", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onMove", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onSay", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onPlayerAttack", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - registerMethod(L, "MonsterType", "onSpawn", MonsterTypeFunctions::luaMonsterTypeEventOnCallback); - - registerMethod(L, "MonsterType", "getSummonList", MonsterTypeFunctions::luaMonsterTypeGetSummonList); - registerMethod(L, "MonsterType", "addSummon", MonsterTypeFunctions::luaMonsterTypeAddSummon); - - registerMethod(L, "MonsterType", "maxSummons", MonsterTypeFunctions::luaMonsterTypeMaxSummons); - - registerMethod(L, "MonsterType", "armor", MonsterTypeFunctions::luaMonsterTypeArmor); - registerMethod(L, "MonsterType", "mitigation", MonsterTypeFunctions::luaMonsterTypeMitigation); - registerMethod(L, "MonsterType", "defense", MonsterTypeFunctions::luaMonsterTypeDefense); - registerMethod(L, "MonsterType", "outfit", MonsterTypeFunctions::luaMonsterTypeOutfit); - registerMethod(L, "MonsterType", "race", MonsterTypeFunctions::luaMonsterTypeRace); - registerMethod(L, "MonsterType", "corpseId", MonsterTypeFunctions::luaMonsterTypeCorpseId); - registerMethod(L, "MonsterType", "manaCost", MonsterTypeFunctions::luaMonsterTypeManaCost); - registerMethod(L, "MonsterType", "baseSpeed", MonsterTypeFunctions::luaMonsterTypeBaseSpeed); - registerMethod(L, "MonsterType", "light", MonsterTypeFunctions::luaMonsterTypeLight); - - registerMethod(L, "MonsterType", "staticAttackChance", MonsterTypeFunctions::luaMonsterTypeStaticAttackChance); - registerMethod(L, "MonsterType", "targetDistance", MonsterTypeFunctions::luaMonsterTypeTargetDistance); - registerMethod(L, "MonsterType", "yellChance", MonsterTypeFunctions::luaMonsterTypeYellChance); - registerMethod(L, "MonsterType", "yellSpeedTicks", MonsterTypeFunctions::luaMonsterTypeYellSpeedTicks); - registerMethod(L, "MonsterType", "changeTargetChance", MonsterTypeFunctions::luaMonsterTypeChangeTargetChance); - registerMethod(L, "MonsterType", "changeTargetSpeed", MonsterTypeFunctions::luaMonsterTypeChangeTargetSpeed); - - registerMethod(L, "MonsterType", "canWalkOnEnergy", MonsterTypeFunctions::luaMonsterTypeCanWalkOnEnergy); - registerMethod(L, "MonsterType", "canWalkOnFire", MonsterTypeFunctions::luaMonsterTypeCanWalkOnFire); - registerMethod(L, "MonsterType", "canWalkOnPoison", MonsterTypeFunctions::luaMonsterTypeCanWalkOnPoison); - - registerMethod(L, "MonsterType", "strategiesTargetNearest", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetNearest); - registerMethod(L, "MonsterType", "strategiesTargetHealth", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetHealth); - registerMethod(L, "MonsterType", "strategiesTargetDamage", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetDamage); - registerMethod(L, "MonsterType", "strategiesTargetRandom", MonsterTypeFunctions::luaMonsterTypeStrategiesTargetRandom); - - registerMethod(L, "MonsterType", "respawnTypePeriod", MonsterTypeFunctions::luaMonsterTypeRespawnTypePeriod); - registerMethod(L, "MonsterType", "respawnTypeIsUnderground", MonsterTypeFunctions::luaMonsterTypeRespawnTypeIsUnderground); - - registerMethod(L, "MonsterType", "bossRace", MonsterTypeFunctions::luaMonsterTypeBossRace); - registerMethod(L, "MonsterType", "bossRaceId", MonsterTypeFunctions::luaMonsterTypeBossRaceId); - - registerMethod(L, "MonsterType", "soundChance", MonsterTypeFunctions::luaMonsterTypeSoundChance); - registerMethod(L, "MonsterType", "soundSpeedTicks", MonsterTypeFunctions::luaMonsterTypeSoundSpeedTicks); - registerMethod(L, "MonsterType", "addSound", MonsterTypeFunctions::luaMonsterTypeAddSound); - registerMethod(L, "MonsterType", "getSounds", MonsterTypeFunctions::luaMonsterTypeGetSounds); - registerMethod(L, "MonsterType", "deathSound", MonsterTypeFunctions::luaMonsterTypedeathSound); - - registerMethod(L, "MonsterType", "variant", MonsterTypeFunctions::luaMonsterTypeVariant); - } + static void init(lua_State* L); private: static void createMonsterTypeLootLuaTable(lua_State* L, const std::vector<LootBlock> &lootList); diff --git a/src/lua/functions/creatures/npc/npc_functions.cpp b/src/lua/functions/creatures/npc/npc_functions.cpp index b18814cdae7..533182ea128 100644 --- a/src/lua/functions/creatures/npc/npc_functions.cpp +++ b/src/lua/functions/creatures/npc/npc_functions.cpp @@ -7,36 +7,76 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" +#include "lua/functions/creatures/npc/npc_functions.hpp" + #include "creatures/creature.hpp" #include "creatures/npcs/npc.hpp" -#include "lua/functions/creatures/npc/npc_functions.hpp" +#include "creatures/players/player.hpp" +#include "game/game.hpp" #include "map/spectators.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void NpcFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Npc", "Creature", NpcFunctions::luaNpcCreate); + Lua::registerMetaMethod(L, "Npc", "__eq", Lua::luaUserdataCompare); + Lua::registerMethod(L, "Npc", "isNpc", NpcFunctions::luaNpcIsNpc); + Lua::registerMethod(L, "Npc", "setMasterPos", NpcFunctions::luaNpcSetMasterPos); + Lua::registerMethod(L, "Npc", "getCurrency", NpcFunctions::luaNpcGetCurrency); + Lua::registerMethod(L, "Npc", "setCurrency", NpcFunctions::luaNpcSetCurrency); + Lua::registerMethod(L, "Npc", "getSpeechBubble", NpcFunctions::luaNpcGetSpeechBubble); + Lua::registerMethod(L, "Npc", "setSpeechBubble", NpcFunctions::luaNpcSetSpeechBubble); + Lua::registerMethod(L, "Npc", "getId", NpcFunctions::luaNpcGetId); + Lua::registerMethod(L, "Npc", "getName", NpcFunctions::luaNpcGetName); + Lua::registerMethod(L, "Npc", "setName", NpcFunctions::luaNpcSetName); + Lua::registerMethod(L, "Npc", "place", NpcFunctions::luaNpcPlace); + Lua::registerMethod(L, "Npc", "say", NpcFunctions::luaNpcSay); + Lua::registerMethod(L, "Npc", "turnToCreature", NpcFunctions::luaNpcTurnToCreature); + Lua::registerMethod(L, "Npc", "setPlayerInteraction", NpcFunctions::luaNpcSetPlayerInteraction); + Lua::registerMethod(L, "Npc", "removePlayerInteraction", NpcFunctions::luaNpcRemovePlayerInteraction); + Lua::registerMethod(L, "Npc", "isInteractingWithPlayer", NpcFunctions::luaNpcIsInteractingWithPlayer); + Lua::registerMethod(L, "Npc", "isInTalkRange", NpcFunctions::luaNpcIsInTalkRange); + Lua::registerMethod(L, "Npc", "isPlayerInteractingOnTopic", NpcFunctions::luaNpcIsPlayerInteractingOnTopic); + Lua::registerMethod(L, "Npc", "openShopWindow", NpcFunctions::luaNpcOpenShopWindow); + Lua::registerMethod(L, "Npc", "openShopWindowTable", NpcFunctions::luaNpcOpenShopWindowTable); + Lua::registerMethod(L, "Npc", "closeShopWindow", NpcFunctions::luaNpcCloseShopWindow); + Lua::registerMethod(L, "Npc", "getShopItem", NpcFunctions::luaNpcGetShopItem); + Lua::registerMethod(L, "Npc", "isMerchant", NpcFunctions::luaNpcIsMerchant); + + Lua::registerMethod(L, "Npc", "move", NpcFunctions::luaNpcMove); + Lua::registerMethod(L, "Npc", "turn", NpcFunctions::luaNpcTurn); + Lua::registerMethod(L, "Npc", "follow", NpcFunctions::luaNpcFollow); + Lua::registerMethod(L, "Npc", "sellItem", NpcFunctions::luaNpcSellItem); + + Lua::registerMethod(L, "Npc", "getDistanceTo", NpcFunctions::luaNpcGetDistanceTo); + + ShopFunctions::init(L); + NpcTypeFunctions::init(L); +} int NpcFunctions::luaNpcCreate(lua_State* L) { // Npc([id or name or userdata]) std::shared_ptr<Npc> npc; if (lua_gettop(L) >= 2) { - if (isNumber(L, 2)) { - npc = g_game().getNpcByID(getNumber<uint32_t>(L, 2)); - } else if (isString(L, 2)) { - npc = g_game().getNpcByName(getString(L, 2)); - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_t::Npc) { + if (Lua::isNumber(L, 2)) { + npc = g_game().getNpcByID(Lua::getNumber<uint32_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + npc = g_game().getNpcByName(Lua::getString(L, 2)); + } else if (Lua::isUserdata(L, 2)) { + if (Lua::getUserdataType(L, 2) != LuaData_t::Npc) { lua_pushnil(L); return 1; } - npc = getUserdataShared<Npc>(L, 2); + npc = Lua::getUserdataShared<Npc>(L, 2); } else { npc = nullptr; } } else { - npc = getUserdataShared<Npc>(L, 1); + npc = Lua::getUserdataShared<Npc>(L, 1); } if (npc) { - pushUserdata<Npc>(L, npc); - setMetatable(L, -1, "Npc"); + Lua::pushUserdata<Npc>(L, npc); + Lua::setMetatable(L, -1, "Npc"); } else { lua_pushnil(L); } @@ -45,30 +85,30 @@ int NpcFunctions::luaNpcCreate(lua_State* L) { int NpcFunctions::luaNpcIsNpc(lua_State* L) { // npc:isNpc() - pushBoolean(L, getUserdataShared<const Npc>(L, 1) != nullptr); + Lua::pushBoolean(L, Lua::getUserdataShared<const Npc>(L, 1) != nullptr); return 1; } int NpcFunctions::luaNpcSetMasterPos(lua_State* L) { // npc:setMasterPos(pos) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const Position &pos = getPosition(L, 2); + const Position &pos = Lua::getPosition(L, 2); npc->setMasterPos(pos); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcGetCurrency(lua_State* L) { // npc:getCurrency() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); } @@ -78,22 +118,22 @@ int NpcFunctions::luaNpcGetCurrency(lua_State* L) { int NpcFunctions::luaNpcSetCurrency(lua_State* L) { // npc:getCurrency() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - npc->setCurrency(getNumber<uint16_t>(L, 2)); + npc->setCurrency(Lua::getNumber<uint16_t>(L, 2)); return 1; } int NpcFunctions::luaNpcGetSpeechBubble(lua_State* L) { // npc:getSpeechBubble() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); } @@ -103,35 +143,35 @@ int NpcFunctions::luaNpcGetSpeechBubble(lua_State* L) { int NpcFunctions::luaNpcSetSpeechBubble(lua_State* L) { // npc:setSpeechBubble(speechBubble) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); } - npc->setSpeechBubble(getNumber<uint8_t>(L, 2)); + npc->setSpeechBubble(Lua::getNumber<uint8_t>(L, 2)); return 1; } int NpcFunctions::luaNpcGetName(lua_State* L) { // npc:getName() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } - pushString(L, npc->getName()); + Lua::pushString(L, npc->getName()); return 1; } int NpcFunctions::luaNpcSetName(lua_State* L) { // npc:setName(name) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - const std::string &name = getString(L, 2); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const std::string &name = Lua::getString(L, 2); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); } @@ -141,19 +181,19 @@ int NpcFunctions::luaNpcSetName(lua_State* L) { int NpcFunctions::luaNpcPlace(lua_State* L) { // npc:place(position[, extended = false[, force = true]]) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } - const Position &position = getPosition(L, 2); - bool extended = getBoolean(L, 3, false); - bool force = getBoolean(L, 4, true); + const Position &position = Lua::getPosition(L, 2); + const bool extended = Lua::getBoolean(L, 3, false); + const bool force = Lua::getBoolean(L, 4, true); if (g_game().placeCreature(npc, position, extended, force)) { - pushUserdata<Npc>(L, npc); - setMetatable(L, -1, "Npc"); + Lua::pushUserdata<Npc>(L, npc); + Lua::setMetatable(L, -1, "Npc"); } else { lua_pushnil(L); } @@ -162,28 +202,28 @@ int NpcFunctions::luaNpcPlace(lua_State* L) { int NpcFunctions::luaNpcSay(lua_State* L) { // npc:say(text[, type = TALKTYPE_PRIVATE_NP[, ghost = false[, target = nullptr[, position]]]]) - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); Position position; if (parameters >= 6) { - position = getPosition(L, 6); + position = Lua::getPosition(L, 6); if (!position.x || !position.y) { - reportErrorFunc("Invalid position specified."); - pushBoolean(L, false); + Lua::reportErrorFunc("Invalid position specified."); + Lua::pushBoolean(L, false); return 1; } } std::shared_ptr<Creature> target = nullptr; if (parameters >= 5) { - target = getCreature(L, 5); + target = Lua::getCreature(L, 5); } - bool ghost = getBoolean(L, 4, false); + const bool ghost = Lua::getBoolean(L, 4, false); - SpeakClasses type = getNumber<SpeakClasses>(L, 3, TALKTYPE_PRIVATE_NP); - const std::string &text = getString(L, 2); - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &type = Lua::getNumber<SpeakClasses>(L, 3, TALKTYPE_PRIVATE_NP); + const std::string &text = Lua::getString(L, 2); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { lua_pushnil(L); return 1; @@ -195,9 +235,9 @@ int NpcFunctions::luaNpcSay(lua_State* L) { } if (position.x != 0) { - pushBoolean(L, g_game().internalCreatureSay(npc, type, text, ghost, &spectators, &position)); + Lua::pushBoolean(L, g_game().internalCreatureSay(npc, type, text, ghost, &spectators, &position)); } else { - pushBoolean(L, g_game().internalCreatureSay(npc, type, text, ghost, &spectators)); + Lua::pushBoolean(L, g_game().internalCreatureSay(npc, type, text, ghost, &spectators)); } return 1; } @@ -208,173 +248,173 @@ int NpcFunctions::luaNpcSay(lua_State* L) { */ int NpcFunctions::luaNpcTurnToCreature(lua_State* L) { // npc:turnToCreature(creature, true) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const auto &creature = Lua::getCreature(L, 2); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } - bool stopEventWalk = getBoolean(L, 3, true); + const bool stopEventWalk = Lua::getBoolean(L, 3, true); if (stopEventWalk) { npc->stopEventWalk(); } npc->turnToCreature(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcSetPlayerInteraction(lua_State* L) { // npc:setPlayerInteraction(creature, topic = 0) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - std::shared_ptr<Creature> creature = getCreature(L, 2); - uint16_t topicId = getNumber<uint16_t>(L, 3, 0); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const auto &creature = Lua::getCreature(L, 2); + const auto topicId = Lua::getNumber<uint16_t>(L, 3, 0); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } npc->setPlayerInteraction(creature->getID(), topicId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcRemovePlayerInteraction(lua_State* L) { // npc:removePlayerInteraction() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const auto &creature = Lua::getCreature(L, 2); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } npc->removePlayerInteraction(creature->getPlayer()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcIsInteractingWithPlayer(lua_State* L) { // npc:isInteractingWithPlayer(creature) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const auto &creature = Lua::getCreature(L, 2); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } - pushBoolean(L, npc->isInteractingWithPlayer(creature->getID())); + Lua::pushBoolean(L, npc->isInteractingWithPlayer(creature->getID())); return 1; } int NpcFunctions::luaNpcIsPlayerInteractingOnTopic(lua_State* L) { // npc:isPlayerInteractingOnTopic(creature, topicId = 0) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - std::shared_ptr<Creature> creature = getCreature(L, 2); - uint32_t topicId = getNumber<uint32_t>(L, 3, 0); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const auto &creature = Lua::getCreature(L, 2); + const auto topicId = Lua::getNumber<uint32_t>(L, 3, 0); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); return 1; } - pushBoolean(L, npc->isPlayerInteractingOnTopic(creature->getID(), topicId)); + Lua::pushBoolean(L, npc->isPlayerInteractingOnTopic(creature->getID(), topicId)); return 1; } int NpcFunctions::luaNpcIsInTalkRange(lua_State* L) { // npc:isInTalkRange(position[, range = 4]) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); - const Position &position = getPosition(L, 2); - uint32_t range = getNumber<uint32_t>(L, 3, 4); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); + const Position &position = Lua::getPosition(L, 2); + const auto range = Lua::getNumber<uint32_t>(L, 3, 4); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } - pushBoolean(L, npc && npc->canInteract(position, range)); + Lua::pushBoolean(L, npc && npc->canInteract(position, range)); return 1; } int NpcFunctions::luaNpcOpenShopWindow(lua_State* L) { // npc:openShopWindow(player) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } player->closeShopWindow(); - pushBoolean(L, player->openShopWindow(npc)); + Lua::pushBoolean(L, player->openShopWindow(npc)); return 1; } int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) { // npc:openShopWindowTable(player, items) - const auto &npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto &player = getUserdataShared<Player>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } if (lua_istable(L, 3) == 0) { - reportError(__FUNCTION__, "item list is not a table."); - pushBoolean(L, false); + Lua::reportError(__FUNCTION__, "item list is not a table."); + Lua::pushBoolean(L, false); return 1; } @@ -383,18 +423,18 @@ int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) { while (lua_next(L, 3) != 0) { const auto tableIndex = lua_gettop(L); - auto itemId = getField<uint16_t>(L, tableIndex, "clientId"); - auto subType = getField<int32_t>(L, tableIndex, "subType"); + auto itemId = Lua::getField<uint16_t>(L, tableIndex, "clientId"); + auto subType = Lua::getField<int32_t>(L, tableIndex, "subType"); if (subType == 0) { - subType = getField<int32_t>(L, tableIndex, "subtype"); + subType = Lua::getField<int32_t>(L, tableIndex, "subtype"); lua_pop(L, 1); } - auto buyPrice = getField<uint32_t>(L, tableIndex, "buy"); - auto sellPrice = getField<uint32_t>(L, tableIndex, "sell"); - auto storageKey = getField<int32_t>(L, tableIndex, "storageKey"); - auto storageValue = getField<int32_t>(L, tableIndex, "storageValue"); - auto itemName = getFieldString(L, tableIndex, "itemName"); + auto buyPrice = Lua::getField<uint32_t>(L, tableIndex, "buy"); + auto sellPrice = Lua::getField<uint32_t>(L, tableIndex, "sell"); + auto storageKey = Lua::getField<int32_t>(L, tableIndex, "storageKey"); + auto storageValue = Lua::getField<int32_t>(L, tableIndex, "storageValue"); + auto itemName = Lua::getFieldString(L, tableIndex, "itemName"); if (itemName.empty()) { itemName = Item::items[itemId].name; } @@ -404,23 +444,23 @@ int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) { lua_pop(L, 3); player->closeShopWindow(); - pushBoolean(L, player->openShopWindow(npc, items)); + Lua::pushBoolean(L, player->openShopWindow(npc, items)); return 1; } int NpcFunctions::luaNpcCloseShopWindow(lua_State* L) { // npc:closeShopWindow(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -428,96 +468,96 @@ int NpcFunctions::luaNpcCloseShopWindow(lua_State* L) { player->closeShopWindow(); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcIsMerchant(lua_State* L) { // npc:isMerchant() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto playerGUID = getNumber<uint32_t>(L, 2, 0); + const auto playerGUID = Lua::getNumber<uint32_t>(L, 2, 0); const auto &shopItems = npc->getShopItemVector(playerGUID); if (shopItems.empty()) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcGetShopItem(lua_State* L) { // npc:getShopItem(itemId) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - auto playerGUID = getNumber<uint32_t>(L, 2, 0); + const auto playerGUID = Lua::getNumber<uint32_t>(L, 2, 0); const auto &shopItems = npc->getShopItemVector(playerGUID); - for (ShopBlock shopBlock : shopItems) { - setField(L, "id", shopBlock.itemId); - setField(L, "name", shopBlock.itemName); - setField(L, "subType", shopBlock.itemSubType); - setField(L, "buyPrice", shopBlock.itemBuyPrice); - setField(L, "sellPrice", shopBlock.itemSellPrice); - setField(L, "storageKey", shopBlock.itemStorageKey); - setField(L, "storageValue", shopBlock.itemStorageValue); + for (const ShopBlock &shopBlock : shopItems) { + Lua::setField(L, "id", shopBlock.itemId); + Lua::setField(L, "name", shopBlock.itemName); + Lua::setField(L, "subType", shopBlock.itemSubType); + Lua::setField(L, "buyPrice", shopBlock.itemBuyPrice); + Lua::setField(L, "sellPrice", shopBlock.itemSellPrice); + Lua::setField(L, "storageKey", shopBlock.itemStorageKey); + Lua::setField(L, "storageValue", shopBlock.itemStorageValue); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcMove(lua_State* L) { // npc:move(direction) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (npc) { - g_game().internalMoveCreature(npc, getNumber<Direction>(L, 2)); + g_game().internalMoveCreature(npc, Lua::getNumber<Direction>(L, 2)); } return 0; } int NpcFunctions::luaNpcTurn(lua_State* L) { // npc:turn(direction) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (npc) { - g_game().internalCreatureTurn(npc, getNumber<Direction>(L, 2)); + g_game().internalCreatureTurn(npc, Lua::getNumber<Direction>(L, 2)); } return 0; } int NpcFunctions::luaNpcFollow(lua_State* L) { // npc:follow(player) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - pushBoolean(L, npc->setFollowCreature(player)); + Lua::pushBoolean(L, npc->setFollowCreature(player)); return 1; } int NpcFunctions::luaNpcGetId(lua_State* L) { // npc:getId() - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); lua_pushnil(L); return 1; } @@ -528,36 +568,36 @@ int NpcFunctions::luaNpcGetId(lua_State* L) { int NpcFunctions::luaNpcSellItem(lua_State* L) { // npc:sellItem(player, itemid, amount, <optional: default: 1> subtype, <optional: default: 0> actionid, <optional: default: false> ignoreCap, <optional: default: false> inBackpacks) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint16_t itemId = getNumber<uint16_t>(L, 3); - double amount = getNumber<double>(L, 4); - uint16_t subType = getNumber<uint16_t>(L, 5, 1); - uint16_t actionId = getNumber<uint16_t>(L, 6, 0); - bool ignoreCap = getBoolean(L, 7, false); - bool inBackpacks = getBoolean(L, 8, false); + auto itemId = Lua::getNumber<uint16_t>(L, 3); + const double amount = Lua::getNumber<double>(L, 4); + const auto subType = Lua::getNumber<uint16_t>(L, 5, 1); + const auto actionId = Lua::getNumber<uint16_t>(L, 6, 0); + const bool ignoreCap = Lua::getBoolean(L, 7, false); + const bool inBackpacks = Lua::getBoolean(L, 8, false); const ItemType &it = Item::items[itemId]; if (it.id == 0) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - uint32_t shoppingBagPrice = 20; - double shoppingBagSlots = 20; - if (std::shared_ptr<Tile> tile = ignoreCap ? player->getTile() : nullptr; tile) { + constexpr uint32_t shoppingBagPrice = 20; + constexpr double shoppingBagSlots = 20; + if (const auto &tile = ignoreCap ? player->getTile() : nullptr; tile) { double slotsNedeed = 0; if (it.stackable) { slotsNedeed = inBackpacks ? std::ceil(std::ceil(amount / it.stackSize) / shoppingBagSlots) : std::ceil(amount / it.stackSize); @@ -566,7 +606,7 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) { } if ((static_cast<double>(tile->getItemList()->size()) + (slotsNedeed - player->getFreeBackpackSlots())) > 30) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); return 1; } @@ -574,7 +614,7 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) { uint64_t pricePerUnit = 0; const auto &shopVector = npc->getShopItemVector(player->getGUID()); - for (ShopBlock shopBlock : shopVector) { + for (const ShopBlock &shopBlock : shopVector) { if (itemId == shopBlock.itemId && shopBlock.itemBuyPrice != 0) { pricePerUnit = shopBlock.itemBuyPrice; break; @@ -584,8 +624,8 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) { const auto &[_, itemsPurchased, backpacksPurchased] = g_game().createItem(player, itemId, amount, subType, actionId, ignoreCap, inBackpacks ? ITEM_SHOPPING_BAG : 0); std::stringstream ss; - uint64_t itemCost = itemsPurchased * pricePerUnit; - uint64_t backpackCost = backpacksPurchased * shoppingBagPrice; + const uint64_t itemCost = itemsPurchased * pricePerUnit; + const uint64_t backpackCost = backpacksPurchased * shoppingBagPrice; if (npc->getCurrency() == ITEM_GOLD_COIN) { if (!g_game().removeMoney(player, itemCost + backpackCost, 0, true)) { g_logger().error("[NpcFunctions::luaNpcSellItem (removeMoney)] - Player {} have a problem for buy item {} on shop for npc {}", player->getName(), itemId, npc->getName()); @@ -640,23 +680,23 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) { } player->sendTextMessage(MESSAGE_TRADE, ss.str()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int NpcFunctions::luaNpcGetDistanceTo(lua_State* L) { // npc:getDistanceTo(uid) - std::shared_ptr<Npc> npc = getUserdataShared<Npc>(L, 1); + const auto &npc = Lua::getUserdataShared<Npc>(L, 1); if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Thing> thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1)); - pushBoolean(L, thing && thing->isPushable()); + const auto &thing = Lua::getScriptEnv()->getThingByUID(Lua::getNumber<uint32_t>(L, -1)); + Lua::pushBoolean(L, thing && thing->isPushable()); if (!thing) { - reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); lua_pushnil(L); return 1; } @@ -666,7 +706,7 @@ int NpcFunctions::luaNpcGetDistanceTo(lua_State* L) { if (npcPos.z != thingPos.z) { lua_pushnumber(L, -1); } else { - int32_t dist = std::max<int32_t>(Position::getDistanceX(npcPos, thingPos), Position::getDistanceY(npcPos, thingPos)); + const int32_t dist = std::max<int32_t>(Position::getDistanceX(npcPos, thingPos), Position::getDistanceY(npcPos, thingPos)); lua_pushnumber(L, dist); } return 1; diff --git a/src/lua/functions/creatures/npc/npc_functions.hpp b/src/lua/functions/creatures/npc/npc_functions.hpp index 1622a15c0e7..4d0adc7335a 100644 --- a/src/lua/functions/creatures/npc/npc_functions.hpp +++ b/src/lua/functions/creatures/npc/npc_functions.hpp @@ -11,46 +11,9 @@ #include "lua/functions/creatures/npc/npc_type_functions.hpp" #include "lua/functions/creatures/npc/shop_functions.hpp" -#include "lua/scripts/luascript.hpp" - -class NpcFunctions final : LuaScriptInterface { +class NpcFunctions { private: - static void init(lua_State* L) { - registerSharedClass(L, "Npc", "Creature", NpcFunctions::luaNpcCreate); - registerMetaMethod(L, "Npc", "__eq", NpcFunctions::luaUserdataCompare); - registerMethod(L, "Npc", "isNpc", NpcFunctions::luaNpcIsNpc); - registerMethod(L, "Npc", "setMasterPos", NpcFunctions::luaNpcSetMasterPos); - registerMethod(L, "Npc", "getCurrency", NpcFunctions::luaNpcGetCurrency); - registerMethod(L, "Npc", "setCurrency", NpcFunctions::luaNpcSetCurrency); - registerMethod(L, "Npc", "getSpeechBubble", NpcFunctions::luaNpcGetSpeechBubble); - registerMethod(L, "Npc", "setSpeechBubble", NpcFunctions::luaNpcSetSpeechBubble); - registerMethod(L, "Npc", "getId", NpcFunctions::luaNpcGetId); - registerMethod(L, "Npc", "getName", NpcFunctions::luaNpcGetName); - registerMethod(L, "Npc", "setName", NpcFunctions::luaNpcSetName); - registerMethod(L, "Npc", "place", NpcFunctions::luaNpcPlace); - registerMethod(L, "Npc", "say", NpcFunctions::luaNpcSay); - registerMethod(L, "Npc", "turnToCreature", NpcFunctions::luaNpcTurnToCreature); - registerMethod(L, "Npc", "setPlayerInteraction", NpcFunctions::luaNpcSetPlayerInteraction); - registerMethod(L, "Npc", "removePlayerInteraction", NpcFunctions::luaNpcRemovePlayerInteraction); - registerMethod(L, "Npc", "isInteractingWithPlayer", NpcFunctions::luaNpcIsInteractingWithPlayer); - registerMethod(L, "Npc", "isInTalkRange", NpcFunctions::luaNpcIsInTalkRange); - registerMethod(L, "Npc", "isPlayerInteractingOnTopic", NpcFunctions::luaNpcIsPlayerInteractingOnTopic); - registerMethod(L, "Npc", "openShopWindow", NpcFunctions::luaNpcOpenShopWindow); - registerMethod(L, "Npc", "openShopWindowTable", NpcFunctions::luaNpcOpenShopWindowTable); - registerMethod(L, "Npc", "closeShopWindow", NpcFunctions::luaNpcCloseShopWindow); - registerMethod(L, "Npc", "getShopItem", NpcFunctions::luaNpcGetShopItem); - registerMethod(L, "Npc", "isMerchant", NpcFunctions::luaNpcIsMerchant); - - registerMethod(L, "Npc", "move", NpcFunctions::luaNpcMove); - registerMethod(L, "Npc", "turn", NpcFunctions::luaNpcTurn); - registerMethod(L, "Npc", "follow", NpcFunctions::luaNpcFollow); - registerMethod(L, "Npc", "sellItem", NpcFunctions::luaNpcSellItem); - - registerMethod(L, "Npc", "getDistanceTo", NpcFunctions::luaNpcGetDistanceTo); - - ShopFunctions::init(L); - NpcTypeFunctions::init(L); - } + static void init(lua_State* L); static int luaNpcCreate(lua_State* L); diff --git a/src/lua/functions/creatures/npc/npc_type_functions.cpp b/src/lua/functions/creatures/npc/npc_type_functions.cpp index 2c4123d91db..84609be95b1 100644 --- a/src/lua/functions/creatures/npc/npc_type_functions.cpp +++ b/src/lua/functions/creatures/npc/npc_type_functions.cpp @@ -7,10 +7,71 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/npcs/npcs.hpp" #include "lua/functions/creatures/npc/npc_type_functions.hpp" -#include "lua/scripts/scripts.hpp" + +#include "config/configmanager.hpp" +#include "creatures/npcs/npcs.hpp" #include "game/game.hpp" +#include "lua/scripts/scripts.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void NpcTypeFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "NpcType", "", NpcTypeFunctions::luaNpcTypeCreate); + Lua::registerMetaMethod(L, "NpcType", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "NpcType", "isPushable", NpcTypeFunctions::luaNpcTypeIsPushable); + Lua::registerMethod(L, "NpcType", "floorChange", NpcTypeFunctions::luaNpcTypeFloorChange); + + Lua::registerMethod(L, "NpcType", "canSpawn", NpcTypeFunctions::luaNpcTypeCanSpawn); + + Lua::registerMethod(L, "NpcType", "canPushItems", NpcTypeFunctions::luaNpcTypeCanPushItems); + Lua::registerMethod(L, "NpcType", "canPushCreatures", NpcTypeFunctions::luaNpcTypeCanPushCreatures); + + Lua::registerMethod(L, "NpcType", "name", NpcTypeFunctions::luaNpcTypeName); + + Lua::registerMethod(L, "NpcType", "nameDescription", NpcTypeFunctions::luaNpcTypeNameDescription); + + Lua::registerMethod(L, "NpcType", "health", NpcTypeFunctions::luaNpcTypeHealth); + Lua::registerMethod(L, "NpcType", "maxHealth", NpcTypeFunctions::luaNpcTypeMaxHealth); + + Lua::registerMethod(L, "NpcType", "getVoices", NpcTypeFunctions::luaNpcTypeGetVoices); + Lua::registerMethod(L, "NpcType", "addVoice", NpcTypeFunctions::luaNpcTypeAddVoice); + + Lua::registerMethod(L, "NpcType", "getCreatureEvents", NpcTypeFunctions::luaNpcTypeGetCreatureEvents); + Lua::registerMethod(L, "NpcType", "registerEvent", NpcTypeFunctions::luaNpcTypeRegisterEvent); + + Lua::registerMethod(L, "NpcType", "eventType", NpcTypeFunctions::luaNpcTypeEventType); + Lua::registerMethod(L, "NpcType", "onThink", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onAppear", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onDisappear", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onMove", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onSay", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onCloseChannel", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onBuyItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onSellItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); + Lua::registerMethod(L, "NpcType", "onCheckItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); + + Lua::registerMethod(L, "NpcType", "outfit", NpcTypeFunctions::luaNpcTypeOutfit); + Lua::registerMethod(L, "NpcType", "baseSpeed", NpcTypeFunctions::luaNpcTypeBaseSpeed); + Lua::registerMethod(L, "NpcType", "walkInterval", NpcTypeFunctions::luaNpcTypeWalkInterval); + Lua::registerMethod(L, "NpcType", "walkRadius", NpcTypeFunctions::luaNpcTypeWalkRadius); + Lua::registerMethod(L, "NpcType", "light", NpcTypeFunctions::luaNpcTypeLight); + + Lua::registerMethod(L, "NpcType", "yellChance", NpcTypeFunctions::luaNpcTypeYellChance); + Lua::registerMethod(L, "NpcType", "yellSpeedTicks", NpcTypeFunctions::luaNpcTypeYellSpeedTicks); + + Lua::registerMethod(L, "NpcType", "respawnTypePeriod", NpcTypeFunctions::luaNpcTypeRespawnTypePeriod); + Lua::registerMethod(L, "NpcType", "respawnTypeIsUnderground", NpcTypeFunctions::luaNpcTypeRespawnTypeIsUnderground); + Lua::registerMethod(L, "NpcType", "speechBubble", NpcTypeFunctions::luaNpcTypeSpeechBubble); + Lua::registerMethod(L, "NpcType", "currency", NpcTypeFunctions::luaNpcTypeCurrency); + + Lua::registerMethod(L, "NpcType", "addShopItem", NpcTypeFunctions::luaNpcTypeAddShopItem); + + Lua::registerMethod(L, "NpcType", "soundChance", NpcTypeFunctions::luaNpcTypeSoundChance); + Lua::registerMethod(L, "NpcType", "soundSpeedTicks", NpcTypeFunctions::luaNpcTypeSoundSpeedTicks); + Lua::registerMethod(L, "NpcType", "addSound", NpcTypeFunctions::luaNpcTypeAddSound); + Lua::registerMethod(L, "NpcType", "getSounds", NpcTypeFunctions::luaNpcTypeGetSounds); +} void NpcTypeFunctions::createNpcTypeShopLuaTable(lua_State* L, const std::vector<ShopBlock> &shopVector) { lua_createtable(L, shopVector.size(), 0); @@ -19,12 +80,12 @@ void NpcTypeFunctions::createNpcTypeShopLuaTable(lua_State* L, const std::vector for (const auto &shopBlock : shopVector) { lua_createtable(L, 0, 5); - setField(L, "itemId", shopBlock.itemId); - setField(L, "itemName", shopBlock.itemName); - setField(L, "itemBuyPrice", shopBlock.itemBuyPrice); - setField(L, "itemSellPrice", shopBlock.itemSellPrice); - setField(L, "itemStorageKey", shopBlock.itemStorageKey); - setField(L, "itemStorageValue", shopBlock.itemStorageValue); + Lua::setField(L, "itemId", shopBlock.itemId); + Lua::setField(L, "itemName", shopBlock.itemName); + Lua::setField(L, "itemBuyPrice", shopBlock.itemBuyPrice); + Lua::setField(L, "itemSellPrice", shopBlock.itemSellPrice); + Lua::setField(L, "itemStorageKey", shopBlock.itemStorageKey); + Lua::setField(L, "itemStorageValue", shopBlock.itemStorageValue); createNpcTypeShopLuaTable(L, shopBlock.childShop); lua_setfield(L, -2, "childShop"); @@ -35,21 +96,21 @@ void NpcTypeFunctions::createNpcTypeShopLuaTable(lua_State* L, const std::vector int NpcTypeFunctions::luaNpcTypeCreate(lua_State* L) { // NpcType(name) - const auto &npcType = g_npcs().getNpcType(getString(L, 1), true); - pushUserdata<NpcType>(L, npcType); - setMetatable(L, -1, "NpcType"); + const auto &npcType = g_npcs().getNpcType(Lua::getString(L, 1), true); + Lua::pushUserdata<NpcType>(L, npcType); + Lua::setMetatable(L, -1, "NpcType"); return 1; } int NpcTypeFunctions::luaNpcTypeIsPushable(lua_State* L) { // get: npcType:isPushable() set: npcType:isPushable(bool) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushBoolean(L, npcType->info.pushable); + Lua::pushBoolean(L, npcType->info.pushable); } else { - npcType->info.pushable = getBoolean(L, 2); - pushBoolean(L, true); + npcType->info.pushable = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -59,13 +120,13 @@ int NpcTypeFunctions::luaNpcTypeIsPushable(lua_State* L) { int NpcTypeFunctions::luaNpcTypeFloorChange(lua_State* L) { // get: npcType:floorChange() set: npcType:floorChange(bool) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushBoolean(L, npcType->info.floorChange); + Lua::pushBoolean(L, npcType->info.floorChange); } else { - npcType->info.floorChange = getBoolean(L, 2); - pushBoolean(L, true); + npcType->info.floorChange = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -75,10 +136,10 @@ int NpcTypeFunctions::luaNpcTypeFloorChange(lua_State* L) { int NpcTypeFunctions::luaNpcTypeCanSpawn(lua_State* L) { // monsterType:canSpawn(pos) - const auto &npcType = getUserdataShared<NpcType>(L, 1); - const Position &position = getPosition(L, 2); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); + const Position &position = Lua::getPosition(L, 2); if (npcType) { - pushBoolean(L, npcType->canSpawn(position)); + Lua::pushBoolean(L, npcType->canSpawn(position)); } else { lua_pushnil(L); } @@ -87,13 +148,13 @@ int NpcTypeFunctions::luaNpcTypeCanSpawn(lua_State* L) { int NpcTypeFunctions::luaNpcTypeCanPushItems(lua_State* L) { // get: npcType:canPushItems() set: npcType:canPushItems(bool) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushBoolean(L, npcType->info.canPushItems); + Lua::pushBoolean(L, npcType->info.canPushItems); } else { - npcType->info.canPushItems = getBoolean(L, 2); - pushBoolean(L, true); + npcType->info.canPushItems = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -103,13 +164,13 @@ int NpcTypeFunctions::luaNpcTypeCanPushItems(lua_State* L) { int NpcTypeFunctions::luaNpcTypeCanPushCreatures(lua_State* L) { // get: npcType:canPushCreatures() set: npcType:canPushCreatures(bool) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushBoolean(L, npcType->info.canPushCreatures); + Lua::pushBoolean(L, npcType->info.canPushCreatures); } else { - npcType->info.canPushCreatures = getBoolean(L, 2); - pushBoolean(L, true); + npcType->info.canPushCreatures = Lua::getBoolean(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -119,13 +180,13 @@ int NpcTypeFunctions::luaNpcTypeCanPushCreatures(lua_State* L) { int32_t NpcTypeFunctions::luaNpcTypeName(lua_State* L) { // get: npcType:name() set: npcType:name(name) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushString(L, npcType->name); + Lua::pushString(L, npcType->name); } else { - npcType->name = getString(L, 2); - pushBoolean(L, true); + npcType->name = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -135,13 +196,13 @@ int32_t NpcTypeFunctions::luaNpcTypeName(lua_State* L) { int NpcTypeFunctions::luaNpcTypeNameDescription(lua_State* L) { // get: npcType:nameDescription() set: npcType:nameDescription(desc) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushString(L, npcType->nameDescription); + Lua::pushString(L, npcType->nameDescription); } else { - npcType->nameDescription = getString(L, 2); - pushBoolean(L, true); + npcType->nameDescription = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -151,13 +212,13 @@ int NpcTypeFunctions::luaNpcTypeNameDescription(lua_State* L) { int NpcTypeFunctions::luaNpcTypeHealth(lua_State* L) { // get: npcType:health() set: npcType:health(health) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.health); } else { - npcType->info.health = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + npcType->info.health = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -167,13 +228,13 @@ int NpcTypeFunctions::luaNpcTypeHealth(lua_State* L) { int NpcTypeFunctions::luaNpcTypeMaxHealth(lua_State* L) { // get: npcType:maxHealth() set: npcType:maxHealth(health) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.healthMax); } else { - npcType->info.healthMax = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + npcType->info.healthMax = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -183,16 +244,16 @@ int NpcTypeFunctions::luaNpcTypeMaxHealth(lua_State* L) { int NpcTypeFunctions::luaNpcTypeAddShopItem(lua_State* L) { // npcType:addShopItem(shop) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { lua_pushnil(L); return 1; } - auto shop = getUserdataShared<Shop>(L, 2); + const auto &shop = Lua::getUserdataShared<Shop>(L, 2); if (shop) { npcType->loadShop(npcType, shop->shopBlock); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -201,15 +262,15 @@ int NpcTypeFunctions::luaNpcTypeAddShopItem(lua_State* L) { int NpcTypeFunctions::luaNpcTypeAddVoice(lua_State* L) { // npcType:addVoice(sentence, interval, chance, yell) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { voiceBlock_t voice; - voice.text = getString(L, 2); - npcType->info.yellSpeedTicks = getNumber<uint32_t>(L, 3); - npcType->info.yellChance = getNumber<uint32_t>(L, 4); - voice.yellText = getBoolean(L, 5); + voice.text = Lua::getString(L, 2); + npcType->info.yellSpeedTicks = Lua::getNumber<uint32_t>(L, 3); + npcType->info.yellChance = Lua::getNumber<uint32_t>(L, 4); + voice.yellText = Lua::getBoolean(L, 5); npcType->info.voiceVector.push_back(voice); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -218,7 +279,7 @@ int NpcTypeFunctions::luaNpcTypeAddVoice(lua_State* L) { int NpcTypeFunctions::luaNpcTypeGetVoices(lua_State* L) { // npcType:getVoices() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { lua_pushnil(L); return 1; @@ -228,8 +289,8 @@ int NpcTypeFunctions::luaNpcTypeGetVoices(lua_State* L) { lua_createtable(L, npcType->info.voiceVector.size(), 0); for (const auto &voiceBlock : npcType->info.voiceVector) { lua_createtable(L, 0, 2); - setField(L, "text", voiceBlock.text); - setField(L, "yellText", voiceBlock.yellText); + Lua::setField(L, "text", voiceBlock.text); + Lua::setField(L, "yellText", voiceBlock.yellText); lua_rawseti(L, -2, ++index); } return 1; @@ -237,7 +298,7 @@ int NpcTypeFunctions::luaNpcTypeGetVoices(lua_State* L) { int NpcTypeFunctions::luaNpcTypeGetCreatureEvents(lua_State* L) { // npcType:getCreatureEvents() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { lua_pushnil(L); return 1; @@ -246,7 +307,7 @@ int NpcTypeFunctions::luaNpcTypeGetCreatureEvents(lua_State* L) { int index = 0; lua_createtable(L, npcType->info.scripts.size(), 0); for (const std::string &creatureEvent : npcType->info.scripts) { - pushString(L, creatureEvent); + Lua::pushString(L, creatureEvent); lua_rawseti(L, -2, ++index); } return 1; @@ -254,10 +315,10 @@ int NpcTypeFunctions::luaNpcTypeGetCreatureEvents(lua_State* L) { int NpcTypeFunctions::luaNpcTypeRegisterEvent(lua_State* L) { // npcType:registerEvent(name) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { - npcType->info.scripts.insert(getString(L, 2)); - pushBoolean(L, true); + npcType->info.scripts.insert(Lua::getString(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -273,13 +334,13 @@ int NpcTypeFunctions::luaNpcTypeEventOnCallback(lua_State* L) { // npcType:onBuyItem(callback) // npcType:onSellItem(callback) // npcType:onCheckItem(callback) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (npcType->loadCallback(&g_scripts().getScriptInterface())) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } - pushBoolean(L, false); + Lua::pushBoolean(L, false); } else { lua_pushnil(L); } @@ -288,10 +349,10 @@ int NpcTypeFunctions::luaNpcTypeEventOnCallback(lua_State* L) { int NpcTypeFunctions::luaNpcTypeEventType(lua_State* L) { // npcType:eventType(event) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { - npcType->info.eventType = getNumber<NpcsEvent_t>(L, 2); - pushBoolean(L, true); + npcType->info.eventType = Lua::getNumber<NpcsEvent_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -300,18 +361,18 @@ int NpcTypeFunctions::luaNpcTypeEventType(lua_State* L) { int NpcTypeFunctions::luaNpcTypeOutfit(lua_State* L) { // get: npcType:outfit() set: npcType:outfit(outfit) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { - pushOutfit(L, npcType->info.outfit); + Lua::pushOutfit(L, npcType->info.outfit); } else { - Outfit_t outfit = getOutfit(L, 2); + Outfit_t outfit = Lua::getOutfit(L, 2); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && outfit.lookType != 0 && !g_game().isLookTypeRegistered(outfit.lookType)) { g_logger().warn("[NpcTypeFunctions::luaNpcTypeOutfit] An unregistered creature looktype type with id '{}' was blocked to prevent client crash.", outfit.lookType); lua_pushnil(L); } else { - npcType->info.outfit = getOutfit(L, 2); - pushBoolean(L, true); + npcType->info.outfit = Lua::getOutfit(L, 2); + Lua::pushBoolean(L, true); } } } else { @@ -322,13 +383,13 @@ int NpcTypeFunctions::luaNpcTypeOutfit(lua_State* L) { int NpcTypeFunctions::luaNpcTypeBaseSpeed(lua_State* L) { // npcType:getBaseSpeed() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.baseSpeed); } else { - npcType->info.baseSpeed = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.baseSpeed = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -338,12 +399,12 @@ int NpcTypeFunctions::luaNpcTypeBaseSpeed(lua_State* L) { int NpcTypeFunctions::luaNpcTypeWalkInterval(lua_State* L) { // get: npcType:walkInterval() set: npcType:walkInterval(interval) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.walkInterval); } else { - npcType->info.walkInterval = getNumber<uint32_t>(L, 2); + npcType->info.walkInterval = Lua::getNumber<uint32_t>(L, 2); lua_pushboolean(L, true); } } else { @@ -354,12 +415,12 @@ int NpcTypeFunctions::luaNpcTypeWalkInterval(lua_State* L) { int NpcTypeFunctions::luaNpcTypeWalkRadius(lua_State* L) { // get: npcType:walkRadius() set: npcType:walkRadius(id) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.walkRadius); } else { - npcType->info.walkRadius = getNumber<int32_t>(L, 2); + npcType->info.walkRadius = Lua::getNumber<int32_t>(L, 2); lua_pushboolean(L, true); } } else { @@ -370,7 +431,7 @@ int NpcTypeFunctions::luaNpcTypeWalkRadius(lua_State* L) { int NpcTypeFunctions::luaNpcTypeLight(lua_State* L) { // get: npcType:light() set: npcType:light(color, level) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { lua_pushnil(L); return 1; @@ -381,27 +442,27 @@ int NpcTypeFunctions::luaNpcTypeLight(lua_State* L) { lua_pushnumber(L, npcType->info.light.color); return 2; } else { - npcType->info.light.color = getNumber<uint8_t>(L, 2); - npcType->info.light.level = getNumber<uint8_t>(L, 3); - pushBoolean(L, true); + npcType->info.light.color = Lua::getNumber<uint8_t>(L, 2); + npcType->info.light.level = Lua::getNumber<uint8_t>(L, 3); + Lua::pushBoolean(L, true); } return 1; } int NpcTypeFunctions::luaNpcTypeYellChance(lua_State* L) { // get: npcType:yellChance() set: npcType:yellChance(chance) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.yellChance); } else { - npcType->info.yellChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.yellChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { - npcType->info.yellChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.yellChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -411,13 +472,13 @@ int NpcTypeFunctions::luaNpcTypeYellChance(lua_State* L) { int NpcTypeFunctions::luaNpcTypeYellSpeedTicks(lua_State* L) { // get: npcType:yellSpeedTicks() set: npcType:yellSpeedTicks(rate) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.yellSpeedTicks); } else { - npcType->info.yellSpeedTicks = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.yellSpeedTicks = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -431,13 +492,13 @@ int NpcTypeFunctions::luaNpcTypeYellSpeedTicks(lua_State* L) { int NpcTypeFunctions::luaNpcTypeRespawnTypePeriod(lua_State* L) { // npcType:respawnTypePeriod() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.respawnType.period); } else { - npcType->info.respawnType.period = getNumber<RespawnPeriod_t>(L, 2); - pushBoolean(L, true); + npcType->info.respawnType.period = Lua::getNumber<RespawnPeriod_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -447,13 +508,13 @@ int NpcTypeFunctions::luaNpcTypeRespawnTypePeriod(lua_State* L) { int NpcTypeFunctions::luaNpcTypeRespawnTypeIsUnderground(lua_State* L) { // npcType:respawnTypeIsUnderground() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (npcType) { if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.respawnType.underground); } else { - npcType->info.respawnType.underground = getNumber<RespawnPeriod_t>(L, 2); - pushBoolean(L, true); + npcType->info.respawnType.underground = Lua::getNumber<RespawnPeriod_t>(L, 2); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -464,18 +525,18 @@ int NpcTypeFunctions::luaNpcTypeRespawnTypeIsUnderground(lua_State* L) { int NpcTypeFunctions::luaNpcTypeSpeechBubble(lua_State* L) { // get = npcType:speechBubble() // set = npcType:speechBubble(newSpeechBubble) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.speechBubble); } else { - npcType->info.speechBubble = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + npcType->info.speechBubble = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } @@ -483,75 +544,75 @@ int NpcTypeFunctions::luaNpcTypeSpeechBubble(lua_State* L) { int NpcTypeFunctions::luaNpcTypeCurrency(lua_State* L) { // get = npcType:currency() // set = npcType:currency(newCurrency) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.currencyId); } else { - npcType->info.currencyId = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + npcType->info.currencyId = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int NpcTypeFunctions::luaNpcTypeSoundChance(lua_State* L) { // get: npcType:soundChance() set: npcType:soundChance(chance) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.soundChance); } else { - npcType->info.soundChance = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.soundChance = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int NpcTypeFunctions::luaNpcTypeSoundSpeedTicks(lua_State* L) { // get: npcType:soundSpeedTicks() set: npcType:soundSpeedTicks(ticks) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } if (lua_gettop(L) == 1) { lua_pushnumber(L, npcType->info.soundSpeedTicks); } else { - npcType->info.soundSpeedTicks = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + npcType->info.soundSpeedTicks = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } return 1; } int NpcTypeFunctions::luaNpcTypeAddSound(lua_State* L) { // npcType:addSound(soundId) - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { - reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_NPC_TYPE_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - npcType->info.soundVector.push_back(getNumber<SoundEffect_t>(L, 2)); - pushBoolean(L, true); + npcType->info.soundVector.push_back(Lua::getNumber<SoundEffect_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int NpcTypeFunctions::luaNpcTypeGetSounds(lua_State* L) { // npcType:getSounds() - const auto &npcType = getUserdataShared<NpcType>(L, 1); + const auto &npcType = Lua::getUserdataShared<NpcType>(L, 1); if (!npcType) { lua_pushnil(L); return 1; diff --git a/src/lua/functions/creatures/npc/npc_type_functions.hpp b/src/lua/functions/creatures/npc/npc_type_functions.hpp index ce799c71f20..1c40cb8ccfc 100644 --- a/src/lua/functions/creatures/npc/npc_type_functions.hpp +++ b/src/lua/functions/creatures/npc/npc_type_functions.hpp @@ -9,67 +9,11 @@ #pragma once -#include "lua/scripts/luascript.hpp" +struct ShopBlock; -class NpcTypeFunctions final : LuaScriptInterface { +class NpcTypeFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "NpcType", "", NpcTypeFunctions::luaNpcTypeCreate); - registerMetaMethod(L, "NpcType", "__eq", NpcTypeFunctions::luaUserdataCompare); - - registerMethod(L, "NpcType", "isPushable", NpcTypeFunctions::luaNpcTypeIsPushable); - registerMethod(L, "NpcType", "floorChange", NpcTypeFunctions::luaNpcTypeFloorChange); - - registerMethod(L, "NpcType", "canSpawn", NpcTypeFunctions::luaNpcTypeCanSpawn); - - registerMethod(L, "NpcType", "canPushItems", NpcTypeFunctions::luaNpcTypeCanPushItems); - registerMethod(L, "NpcType", "canPushCreatures", NpcTypeFunctions::luaNpcTypeCanPushCreatures); - - registerMethod(L, "NpcType", "name", NpcTypeFunctions::luaNpcTypeName); - - registerMethod(L, "NpcType", "nameDescription", NpcTypeFunctions::luaNpcTypeNameDescription); - - registerMethod(L, "NpcType", "health", NpcTypeFunctions::luaNpcTypeHealth); - registerMethod(L, "NpcType", "maxHealth", NpcTypeFunctions::luaNpcTypeMaxHealth); - - registerMethod(L, "NpcType", "getVoices", NpcTypeFunctions::luaNpcTypeGetVoices); - registerMethod(L, "NpcType", "addVoice", NpcTypeFunctions::luaNpcTypeAddVoice); - - registerMethod(L, "NpcType", "getCreatureEvents", NpcTypeFunctions::luaNpcTypeGetCreatureEvents); - registerMethod(L, "NpcType", "registerEvent", NpcTypeFunctions::luaNpcTypeRegisterEvent); - - registerMethod(L, "NpcType", "eventType", NpcTypeFunctions::luaNpcTypeEventType); - registerMethod(L, "NpcType", "onThink", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onAppear", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onDisappear", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onMove", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onSay", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onCloseChannel", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onBuyItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onSellItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); - registerMethod(L, "NpcType", "onCheckItem", NpcTypeFunctions::luaNpcTypeEventOnCallback); - - registerMethod(L, "NpcType", "outfit", NpcTypeFunctions::luaNpcTypeOutfit); - registerMethod(L, "NpcType", "baseSpeed", NpcTypeFunctions::luaNpcTypeBaseSpeed); - registerMethod(L, "NpcType", "walkInterval", NpcTypeFunctions::luaNpcTypeWalkInterval); - registerMethod(L, "NpcType", "walkRadius", NpcTypeFunctions::luaNpcTypeWalkRadius); - registerMethod(L, "NpcType", "light", NpcTypeFunctions::luaNpcTypeLight); - - registerMethod(L, "NpcType", "yellChance", NpcTypeFunctions::luaNpcTypeYellChance); - registerMethod(L, "NpcType", "yellSpeedTicks", NpcTypeFunctions::luaNpcTypeYellSpeedTicks); - - registerMethod(L, "NpcType", "respawnTypePeriod", NpcTypeFunctions::luaNpcTypeRespawnTypePeriod); - registerMethod(L, "NpcType", "respawnTypeIsUnderground", NpcTypeFunctions::luaNpcTypeRespawnTypeIsUnderground); - registerMethod(L, "NpcType", "speechBubble", NpcTypeFunctions::luaNpcTypeSpeechBubble); - registerMethod(L, "NpcType", "currency", NpcTypeFunctions::luaNpcTypeCurrency); - - registerMethod(L, "NpcType", "addShopItem", NpcTypeFunctions::luaNpcTypeAddShopItem); - - registerMethod(L, "NpcType", "soundChance", NpcTypeFunctions::luaNpcTypeSoundChance); - registerMethod(L, "NpcType", "soundSpeedTicks", NpcTypeFunctions::luaNpcTypeSoundSpeedTicks); - registerMethod(L, "NpcType", "addSound", NpcTypeFunctions::luaNpcTypeAddSound); - registerMethod(L, "NpcType", "getSounds", NpcTypeFunctions::luaNpcTypeGetSounds); - } + static void init(lua_State* L); private: static void createNpcTypeShopLuaTable(lua_State* L, const std::vector<ShopBlock> &shopVector); @@ -77,7 +21,6 @@ class NpcTypeFunctions final : LuaScriptInterface { static int luaNpcTypeIsPushable(lua_State* L); static int luaNpcTypeFloorChange(lua_State* L); - static int luaNpcTypeRespawnType(lua_State* L); static int luaNpcTypeCanSpawn(lua_State* L); static int luaNpcTypeCanPushItems(lua_State* L); diff --git a/src/lua/functions/creatures/npc/shop_functions.cpp b/src/lua/functions/creatures/npc/shop_functions.cpp index 388bda0e977..04d62ae585b 100644 --- a/src/lua/functions/creatures/npc/shop_functions.cpp +++ b/src/lua/functions/creatures/npc/shop_functions.cpp @@ -7,23 +7,41 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/npcs/npcs.hpp" #include "lua/functions/creatures/npc/shop_functions.hpp" +#include "creatures/npcs/npcs.hpp" + +#include "items/item.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ShopFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Shop", "", ShopFunctions::luaCreateShop); + Lua::registerMethod(L, "Shop", "setId", ShopFunctions::luaShopSetId); + Lua::registerMethod(L, "Shop", "setIdFromName", ShopFunctions::luaShopSetIdFromName); + Lua::registerMethod(L, "Shop", "setNameItem", ShopFunctions::luaShopSetNameItem); + Lua::registerMethod(L, "Shop", "setCount", ShopFunctions::luaShopSetCount); + Lua::registerMethod(L, "Shop", "setBuyPrice", ShopFunctions::luaShopSetBuyPrice); + Lua::registerMethod(L, "Shop", "setSellPrice", ShopFunctions::luaShopSetSellPrice); + Lua::registerMethod(L, "Shop", "setStorageKey", ShopFunctions::luaShopSetStorageKey); + Lua::registerMethod(L, "Shop", "setStorageValue", ShopFunctions::luaShopSetStorageValue); + Lua::registerMethod(L, "Shop", "addChildShop", ShopFunctions::luaShopAddChildShop); +} + int ShopFunctions::luaCreateShop(lua_State* L) { // Shop() will create a new shop item - pushUserdata<Shop>(L, std::make_shared<Shop>()); - setMetatable(L, -1, "Shop"); + Lua::pushUserdata<Shop>(L, std::make_shared<Shop>()); + Lua::setMetatable(L, -1, "Shop"); return 1; } int ShopFunctions::luaShopSetId(lua_State* L) { // shop:setId(id) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - if (isNumber(L, 2)) { - shop->shopBlock.itemId = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + if (Lua::isNumber(L, 2)) { + shop->shopBlock.itemId = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { g_logger().warn("[ShopFunctions::luaShopSetId] - " "Unknown shop item shop, int value expected"); @@ -37,10 +55,10 @@ int ShopFunctions::luaShopSetId(lua_State* L) { int ShopFunctions::luaShopSetIdFromName(lua_State* L) { // shop:setIdFromName(name) - const auto &shop = getUserdataShared<Shop>(L, 1); - if (shop && isString(L, 2)) { - auto name = getString(L, 2); - auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name)); + const auto &shop = Lua::getUserdataShared<Shop>(L, 1); + if (shop && Lua::isString(L, 2)) { + auto name = Lua::getString(L, 2); + const auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name)); if (ids.first == Item::items.nameToItems.cend()) { g_logger().warn("[ShopFunctions::luaShopSetIdFromName] - " @@ -59,7 +77,7 @@ int ShopFunctions::luaShopSetIdFromName(lua_State* L) { } shop->shopBlock.itemId = ids.first->second; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { g_logger().warn("[ShopFunctions::luaShopSetIdFromName] - " "Unknown shop item shop, string value expected"); @@ -70,9 +88,9 @@ int ShopFunctions::luaShopSetIdFromName(lua_State* L) { int ShopFunctions::luaShopSetNameItem(lua_State* L) { // shop:setNameItem(name) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemName = getString(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemName = Lua::getString(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -81,9 +99,9 @@ int ShopFunctions::luaShopSetNameItem(lua_State* L) { int ShopFunctions::luaShopSetCount(lua_State* L) { // shop:setCount(count) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemSubType = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemSubType = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -92,9 +110,9 @@ int ShopFunctions::luaShopSetCount(lua_State* L) { int ShopFunctions::luaShopSetBuyPrice(lua_State* L) { // shop:setBuyPrice(price) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemBuyPrice = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemBuyPrice = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -103,9 +121,9 @@ int ShopFunctions::luaShopSetBuyPrice(lua_State* L) { int ShopFunctions::luaShopSetSellPrice(lua_State* L) { // shop:setSellPrice(chance) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemSellPrice = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemSellPrice = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -114,9 +132,9 @@ int ShopFunctions::luaShopSetSellPrice(lua_State* L) { int ShopFunctions::luaShopSetStorageKey(lua_State* L) { // shop:setStorageKey(storage) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemStorageKey = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemStorageKey = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -125,9 +143,9 @@ int ShopFunctions::luaShopSetStorageKey(lua_State* L) { int ShopFunctions::luaShopSetStorageValue(lua_State* L) { // shop:setStorageValue(value) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.itemStorageValue = getNumber<uint32_t>(L, 2); - pushBoolean(L, true); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.itemStorageValue = Lua::getNumber<uint32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -136,8 +154,8 @@ int ShopFunctions::luaShopSetStorageValue(lua_State* L) { int ShopFunctions::luaShopAddChildShop(lua_State* L) { // shop:addChildShop(shop) - if (const auto &shop = getUserdataShared<Shop>(L, 1)) { - shop->shopBlock.childShop.push_back(getUserdataShared<Shop>(L, 2)->shopBlock); + if (const auto &shop = Lua::getUserdataShared<Shop>(L, 1)) { + shop->shopBlock.childShop.push_back(Lua::getUserdataShared<Shop>(L, 2)->shopBlock); } else { lua_pushnil(L); } diff --git a/src/lua/functions/creatures/npc/shop_functions.hpp b/src/lua/functions/creatures/npc/shop_functions.hpp index e5a6c9943cc..7bd91568601 100644 --- a/src/lua/functions/creatures/npc/shop_functions.hpp +++ b/src/lua/functions/creatures/npc/shop_functions.hpp @@ -9,22 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ShopFunctions final : LuaScriptInterface { +class ShopFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Shop", "", ShopFunctions::luaCreateShop); - registerMethod(L, "Shop", "setId", ShopFunctions::luaShopSetId); - registerMethod(L, "Shop", "setIdFromName", ShopFunctions::luaShopSetIdFromName); - registerMethod(L, "Shop", "setNameItem", ShopFunctions::luaShopSetNameItem); - registerMethod(L, "Shop", "setCount", ShopFunctions::luaShopSetCount); - registerMethod(L, "Shop", "setBuyPrice", ShopFunctions::luaShopSetBuyPrice); - registerMethod(L, "Shop", "setSellPrice", ShopFunctions::luaShopSetSellPrice); - registerMethod(L, "Shop", "setStorageKey", ShopFunctions::luaShopSetStorageKey); - registerMethod(L, "Shop", "setStorageValue", ShopFunctions::luaShopSetStorageValue); - registerMethod(L, "Shop", "addChildShop", ShopFunctions::luaShopAddChildShop); - } + static void init(lua_State* L); private: static int luaCreateShop(lua_State* L); diff --git a/src/lua/functions/creatures/player/group_functions.cpp b/src/lua/functions/creatures/player/group_functions.cpp index 2fd414a2e4a..0c538a10eef 100644 --- a/src/lua/functions/creatures/player/group_functions.cpp +++ b/src/lua/functions/creatures/player/group_functions.cpp @@ -7,18 +7,33 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/player/group_functions.hpp" + #include "creatures/players/grouping/groups.hpp" #include "game/game.hpp" -#include "lua/functions/creatures/player/group_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void GroupFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Group", "", GroupFunctions::luaGroupCreate); + Lua::registerMetaMethod(L, "Group", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Group", "getId", GroupFunctions::luaGroupGetId); + Lua::registerMethod(L, "Group", "getName", GroupFunctions::luaGroupGetName); + Lua::registerMethod(L, "Group", "getFlags", GroupFunctions::luaGroupGetFlags); + Lua::registerMethod(L, "Group", "getAccess", GroupFunctions::luaGroupGetAccess); + Lua::registerMethod(L, "Group", "getMaxDepotItems", GroupFunctions::luaGroupGetMaxDepotItems); + Lua::registerMethod(L, "Group", "getMaxVipEntries", GroupFunctions::luaGroupGetMaxVipEntries); + Lua::registerMethod(L, "Group", "hasFlag", GroupFunctions::luaGroupHasFlag); +} int GroupFunctions::luaGroupCreate(lua_State* L) { // Group(id) - uint32_t id = getNumber<uint32_t>(L, 2); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); const auto &group = g_game().groups.getGroup(id); if (group) { - pushUserdata<Group>(L, group); - setMetatable(L, -1, "Group"); + Lua::pushUserdata<Group>(L, group); + Lua::setMetatable(L, -1, "Group"); } else { lua_pushnil(L); } @@ -27,7 +42,7 @@ int GroupFunctions::luaGroupCreate(lua_State* L) { int GroupFunctions::luaGroupGetId(lua_State* L) { // group:getId() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { lua_pushnumber(L, group->id); } else { @@ -38,9 +53,9 @@ int GroupFunctions::luaGroupGetId(lua_State* L) { int GroupFunctions::luaGroupGetName(lua_State* L) { // group:getName() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { - pushString(L, group->name); + Lua::pushString(L, group->name); } else { lua_pushnil(L); } @@ -49,7 +64,7 @@ int GroupFunctions::luaGroupGetName(lua_State* L) { int GroupFunctions::luaGroupGetFlags(lua_State* L) { // group:getFlags() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { std::bitset<magic_enum::enum_integer(PlayerFlags_t::FlagLast)> flags; for (uint8_t i = 0; i < magic_enum::enum_integer(PlayerFlags_t::FlagLast); ++i) { @@ -66,9 +81,9 @@ int GroupFunctions::luaGroupGetFlags(lua_State* L) { int GroupFunctions::luaGroupGetAccess(lua_State* L) { // group:getAccess() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { - pushBoolean(L, group->access); + Lua::pushBoolean(L, group->access); } else { lua_pushnil(L); } @@ -77,7 +92,7 @@ int GroupFunctions::luaGroupGetAccess(lua_State* L) { int GroupFunctions::luaGroupGetMaxDepotItems(lua_State* L) { // group:getMaxDepotItems() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { lua_pushnumber(L, group->maxDepotItems); } else { @@ -88,7 +103,7 @@ int GroupFunctions::luaGroupGetMaxDepotItems(lua_State* L) { int GroupFunctions::luaGroupGetMaxVipEntries(lua_State* L) { // group:getMaxVipEntries() - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { lua_pushnumber(L, group->maxVipEntries); } else { @@ -99,10 +114,10 @@ int GroupFunctions::luaGroupGetMaxVipEntries(lua_State* L) { int GroupFunctions::luaGroupHasFlag(lua_State* L) { // group:hasFlag(flag) - const auto &group = getUserdataShared<Group>(L, 1); + const auto &group = Lua::getUserdataShared<Group>(L, 1); if (group) { - auto flag = static_cast<PlayerFlags_t>(getNumber<int>(L, 2)); - pushBoolean(L, group->flags[Groups::getFlagNumber(flag)]); + const auto flag = static_cast<PlayerFlags_t>(Lua::getNumber<int>(L, 2)); + Lua::pushBoolean(L, group->flags[Groups::getFlagNumber(flag)]); } else { lua_pushnil(L); } diff --git a/src/lua/functions/creatures/player/group_functions.hpp b/src/lua/functions/creatures/player/group_functions.hpp index 4a33d1b988e..76774df5bb2 100644 --- a/src/lua/functions/creatures/player/group_functions.hpp +++ b/src/lua/functions/creatures/player/group_functions.hpp @@ -9,22 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class GroupFunctions final : LuaScriptInterface { +class GroupFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Group", "", GroupFunctions::luaGroupCreate); - registerMetaMethod(L, "Group", "__eq", GroupFunctions::luaUserdataCompare); - - registerMethod(L, "Group", "getId", GroupFunctions::luaGroupGetId); - registerMethod(L, "Group", "getName", GroupFunctions::luaGroupGetName); - registerMethod(L, "Group", "getFlags", GroupFunctions::luaGroupGetFlags); - registerMethod(L, "Group", "getAccess", GroupFunctions::luaGroupGetAccess); - registerMethod(L, "Group", "getMaxDepotItems", GroupFunctions::luaGroupGetMaxDepotItems); - registerMethod(L, "Group", "getMaxVipEntries", GroupFunctions::luaGroupGetMaxVipEntries); - registerMethod(L, "Group", "hasFlag", GroupFunctions::luaGroupHasFlag); - } + static void init(lua_State* L); private: static int luaGroupCreate(lua_State* L); diff --git a/src/lua/functions/creatures/player/guild_functions.cpp b/src/lua/functions/creatures/player/guild_functions.cpp index d5706e0609b..62082d4f43a 100644 --- a/src/lua/functions/creatures/player/guild_functions.cpp +++ b/src/lua/functions/creatures/player/guild_functions.cpp @@ -7,16 +7,37 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/player/guild_functions.hpp" + #include "game/game.hpp" #include "creatures/players/grouping/guild.hpp" -#include "lua/functions/creatures/player/guild_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void GuildFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Guild", "", GuildFunctions::luaGuildCreate); + Lua::registerMetaMethod(L, "Guild", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Guild", "getId", GuildFunctions::luaGuildGetId); + Lua::registerMethod(L, "Guild", "getName", GuildFunctions::luaGuildGetName); + Lua::registerMethod(L, "Guild", "getMembersOnline", GuildFunctions::luaGuildGetMembersOnline); + + Lua::registerMethod(L, "Guild", "getBankBalance", GuildFunctions::luaGuildGetBankBalance); + Lua::registerMethod(L, "Guild", "setBankBalance", GuildFunctions::luaGuildSetBankBalance); + + Lua::registerMethod(L, "Guild", "addRank", GuildFunctions::luaGuildAddRank); + Lua::registerMethod(L, "Guild", "getRankById", GuildFunctions::luaGuildGetRankById); + Lua::registerMethod(L, "Guild", "getRankByLevel", GuildFunctions::luaGuildGetRankByLevel); + + Lua::registerMethod(L, "Guild", "getMotd", GuildFunctions::luaGuildGetMotd); + Lua::registerMethod(L, "Guild", "setMotd", GuildFunctions::luaGuildSetMotd); +} int GuildFunctions::luaGuildCreate(lua_State* L) { - uint32_t id = getNumber<uint32_t>(L, 2); - const auto guild = g_game().getGuild(id); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); + const auto &guild = g_game().getGuild(id); if (guild) { - pushUserdata<Guild>(L, guild); - setMetatable(L, -1, "Guild"); + Lua::pushUserdata<Guild>(L, guild); + Lua::setMetatable(L, -1, "Guild"); } else { lua_pushnil(L); } @@ -24,7 +45,7 @@ int GuildFunctions::luaGuildCreate(lua_State* L) { } int GuildFunctions::luaGuildGetId(lua_State* L) { - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (guild) { lua_pushnumber(L, guild->getId()); } else { @@ -35,18 +56,18 @@ int GuildFunctions::luaGuildGetId(lua_State* L) { int GuildFunctions::luaGuildGetName(lua_State* L) { // guild:getName() - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - pushString(L, guild->getName()); + Lua::pushString(L, guild->getName()); return 1; } int GuildFunctions::luaGuildGetMembersOnline(lua_State* L) { // guild:getMembersOnline() - const auto guild = getUserdataShared<const Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<const Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; @@ -56,9 +77,9 @@ int GuildFunctions::luaGuildGetMembersOnline(lua_State* L) { lua_createtable(L, members.size(), 0); int index = 0; - for (std::shared_ptr<Player> player : members) { - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + for (const auto &player : members) { + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; @@ -66,7 +87,7 @@ int GuildFunctions::luaGuildGetMembersOnline(lua_State* L) { int GuildFunctions::luaGuildGetBankBalance(lua_State* L) { // guild:getBankBalance() - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; @@ -77,47 +98,47 @@ int GuildFunctions::luaGuildGetBankBalance(lua_State* L) { int GuildFunctions::luaGuildSetBankBalance(lua_State* L) { // guild:setBankBalance(bankBalance) - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - guild->setBankBalance(getNumber<uint64_t>(L, 2)); - pushBoolean(L, true); + guild->setBankBalance(Lua::getNumber<uint64_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int GuildFunctions::luaGuildAddRank(lua_State* L) { // guild:addRank(id, name, level) - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - uint32_t id = getNumber<uint32_t>(L, 2); - const std::string &name = getString(L, 3); - uint8_t level = getNumber<uint8_t>(L, 4); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); + const std::string &name = Lua::getString(L, 3); + const uint8_t level = Lua::getNumber<uint8_t>(L, 4); guild->addRank(id, name, level); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int GuildFunctions::luaGuildGetRankById(lua_State* L) { // guild:getRankById(id) - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - uint32_t id = getNumber<uint32_t>(L, 2); - GuildRank_ptr rank = guild->getRankById(id); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); + const GuildRank_ptr rank = guild->getRankById(id); if (rank) { lua_createtable(L, 0, 3); - setField(L, "id", rank->id); - setField(L, "name", rank->name); - setField(L, "level", rank->level); + Lua::setField(L, "id", rank->id); + Lua::setField(L, "name", rank->name); + Lua::setField(L, "level", rank->level); } else { lua_pushnil(L); } @@ -126,19 +147,19 @@ int GuildFunctions::luaGuildGetRankById(lua_State* L) { int GuildFunctions::luaGuildGetRankByLevel(lua_State* L) { // guild:getRankByLevel(level) - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - uint8_t level = getNumber<uint8_t>(L, 2); - GuildRank_ptr rank = guild->getRankByLevel(level); + const uint8_t level = Lua::getNumber<uint8_t>(L, 2); + const GuildRank_ptr rank = guild->getRankByLevel(level); if (rank) { lua_createtable(L, 0, 3); - setField(L, "id", rank->id); - setField(L, "name", rank->name); - setField(L, "level", rank->level); + Lua::setField(L, "id", rank->id); + Lua::setField(L, "name", rank->name); + Lua::setField(L, "level", rank->level); } else { lua_pushnil(L); } @@ -147,24 +168,24 @@ int GuildFunctions::luaGuildGetRankByLevel(lua_State* L) { int GuildFunctions::luaGuildGetMotd(lua_State* L) { // guild:getMotd() - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - pushString(L, guild->getMotd()); + Lua::pushString(L, guild->getMotd()); return 1; } int GuildFunctions::luaGuildSetMotd(lua_State* L) { // guild:setMotd(motd) - const auto guild = getUserdataShared<Guild>(L, 1); + const auto &guild = Lua::getUserdataShared<Guild>(L, 1); if (!guild) { lua_pushnil(L); return 1; } - const std::string &motd = getString(L, 2); + const std::string &motd = Lua::getString(L, 2); guild->setMotd(motd); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/creatures/player/guild_functions.hpp b/src/lua/functions/creatures/player/guild_functions.hpp index e5c48244415..9c5ded2b63b 100644 --- a/src/lua/functions/creatures/player/guild_functions.hpp +++ b/src/lua/functions/creatures/player/guild_functions.hpp @@ -9,28 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class GuildFunctions final : LuaScriptInterface { +class GuildFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Guild", "", GuildFunctions::luaGuildCreate); - registerMetaMethod(L, "Guild", "__eq", GuildFunctions::luaUserdataCompare); - - registerMethod(L, "Guild", "getId", GuildFunctions::luaGuildGetId); - registerMethod(L, "Guild", "getName", GuildFunctions::luaGuildGetName); - registerMethod(L, "Guild", "getMembersOnline", GuildFunctions::luaGuildGetMembersOnline); - - registerMethod(L, "Guild", "getBankBalance", GuildFunctions::luaGuildGetBankBalance); - registerMethod(L, "Guild", "setBankBalance", GuildFunctions::luaGuildSetBankBalance); - - registerMethod(L, "Guild", "addRank", GuildFunctions::luaGuildAddRank); - registerMethod(L, "Guild", "getRankById", GuildFunctions::luaGuildGetRankById); - registerMethod(L, "Guild", "getRankByLevel", GuildFunctions::luaGuildGetRankByLevel); - - registerMethod(L, "Guild", "getMotd", GuildFunctions::luaGuildGetMotd); - registerMethod(L, "Guild", "setMotd", GuildFunctions::luaGuildSetMotd); - } + static void init(lua_State* L); private: static int luaGuildCreate(lua_State* L); diff --git a/src/lua/functions/creatures/player/mount_functions.cpp b/src/lua/functions/creatures/player/mount_functions.cpp index 3decd6b2321..6c6d929ed5c 100644 --- a/src/lua/functions/creatures/player/mount_functions.cpp +++ b/src/lua/functions/creatures/player/mount_functions.cpp @@ -7,25 +7,37 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/player/mount_functions.hpp" + #include "creatures/appearance/mounts/mounts.hpp" #include "game/game.hpp" -#include "lua/functions/creatures/player/mount_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void MountFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Mount", "", MountFunctions::luaCreateMount); + Lua::registerMetaMethod(L, "Mount", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Mount", "getName", MountFunctions::luaMountGetName); + Lua::registerMethod(L, "Mount", "getId", MountFunctions::luaMountGetId); + Lua::registerMethod(L, "Mount", "getClientId", MountFunctions::luaMountGetClientId); + Lua::registerMethod(L, "Mount", "getSpeed", MountFunctions::luaMountGetSpeed); +} int MountFunctions::luaCreateMount(lua_State* L) { // Mount(id or name) std::shared_ptr<Mount> mount; - if (isNumber(L, 2)) { - mount = g_game().mounts.getMountByID(getNumber<uint8_t>(L, 2)); - } else if (isString(L, 2)) { - std::string mountName = getString(L, 2); - mount = g_game().mounts.getMountByName(mountName); + if (Lua::isNumber(L, 2)) { + mount = g_game().mounts->getMountByID(Lua::getNumber<uint8_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + std::string mountName = Lua::getString(L, 2); + mount = g_game().mounts->getMountByName(mountName); } else { mount = nullptr; } if (mount) { - pushUserdata<Mount>(L, mount); - setMetatable(L, -1, "Mount"); + Lua::pushUserdata<Mount>(L, mount); + Lua::setMetatable(L, -1, "Mount"); } else { lua_pushnil(L); } @@ -35,9 +47,9 @@ int MountFunctions::luaCreateMount(lua_State* L) { int MountFunctions::luaMountGetName(lua_State* L) { // mount:getName() - const std::shared_ptr<Mount> mount = getUserdataShared<Mount>(L, 1); + const auto &mount = Lua::getUserdataShared<Mount>(L, 1); if (mount) { - pushString(L, mount->name); + Lua::pushString(L, mount->name); } else { lua_pushnil(L); } @@ -47,7 +59,7 @@ int MountFunctions::luaMountGetName(lua_State* L) { int MountFunctions::luaMountGetId(lua_State* L) { // mount:getId() - const std::shared_ptr<Mount> mount = getUserdataShared<Mount>(L, 1); + const auto &mount = Lua::getUserdataShared<Mount>(L, 1); if (mount) { lua_pushnumber(L, mount->id); } else { @@ -59,7 +71,7 @@ int MountFunctions::luaMountGetId(lua_State* L) { int MountFunctions::luaMountGetClientId(lua_State* L) { // mount:getClientId() - const std::shared_ptr<Mount> mount = getUserdataShared<Mount>(L, 1); + const auto &mount = Lua::getUserdataShared<Mount>(L, 1); if (mount) { lua_pushnumber(L, mount->clientId); } else { @@ -71,7 +83,7 @@ int MountFunctions::luaMountGetClientId(lua_State* L) { int MountFunctions::luaMountGetSpeed(lua_State* L) { // mount:getSpeed() - const std::shared_ptr<Mount> mount = getUserdataShared<Mount>(L, 1); + const auto &mount = Lua::getUserdataShared<Mount>(L, 1); if (mount) { lua_pushnumber(L, mount->speed); } else { diff --git a/src/lua/functions/creatures/player/mount_functions.hpp b/src/lua/functions/creatures/player/mount_functions.hpp index 3a4db6d6f92..e49e67173e3 100644 --- a/src/lua/functions/creatures/player/mount_functions.hpp +++ b/src/lua/functions/creatures/player/mount_functions.hpp @@ -9,19 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class MountFunctions final : LuaScriptInterface { +class MountFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Mount", "", MountFunctions::luaCreateMount); - registerMetaMethod(L, "Mount", "__eq", MountFunctions::luaUserdataCompare); - - registerMethod(L, "Mount", "getName", MountFunctions::luaMountGetName); - registerMethod(L, "Mount", "getId", MountFunctions::luaMountGetId); - registerMethod(L, "Mount", "getClientId", MountFunctions::luaMountGetClientId); - registerMethod(L, "Mount", "getSpeed", MountFunctions::luaMountGetSpeed); - } + static void init(lua_State* L); private: static int luaCreateMount(lua_State* L); diff --git a/src/lua/functions/creatures/player/party_functions.cpp b/src/lua/functions/creatures/player/party_functions.cpp index 1791016bde3..5c43593282a 100644 --- a/src/lua/functions/creatures/player/party_functions.cpp +++ b/src/lua/functions/creatures/player/party_functions.cpp @@ -7,26 +7,48 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/creatures/player/party_functions.hpp" + #include "creatures/players/grouping/party.hpp" #include "creatures/players/player.hpp" #include "game/game.hpp" -#include "lua/functions/creatures/player/party_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void PartyFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Party", "", PartyFunctions::luaPartyCreate); + Lua::registerMetaMethod(L, "Party", "__eq", Lua::luaUserdataCompare); + Lua::registerMethod(L, "Party", "disband", PartyFunctions::luaPartyDisband); + Lua::registerMethod(L, "Party", "getLeader", PartyFunctions::luaPartyGetLeader); + Lua::registerMethod(L, "Party", "setLeader", PartyFunctions::luaPartySetLeader); + Lua::registerMethod(L, "Party", "getMembers", PartyFunctions::luaPartyGetMembers); + Lua::registerMethod(L, "Party", "getMemberCount", PartyFunctions::luaPartyGetMemberCount); + Lua::registerMethod(L, "Party", "getInvitees", PartyFunctions::luaPartyGetInvitees); + Lua::registerMethod(L, "Party", "getInviteeCount", PartyFunctions::luaPartyGetInviteeCount); + Lua::registerMethod(L, "Party", "addInvite", PartyFunctions::luaPartyAddInvite); + Lua::registerMethod(L, "Party", "removeInvite", PartyFunctions::luaPartyRemoveInvite); + Lua::registerMethod(L, "Party", "addMember", PartyFunctions::luaPartyAddMember); + Lua::registerMethod(L, "Party", "removeMember", PartyFunctions::luaPartyRemoveMember); + Lua::registerMethod(L, "Party", "isSharedExperienceActive", PartyFunctions::luaPartyIsSharedExperienceActive); + Lua::registerMethod(L, "Party", "isSharedExperienceEnabled", PartyFunctions::luaPartyIsSharedExperienceEnabled); + Lua::registerMethod(L, "Party", "shareExperience", PartyFunctions::luaPartyShareExperience); + Lua::registerMethod(L, "Party", "setSharedExperience", PartyFunctions::luaPartySetSharedExperience); +} int32_t PartyFunctions::luaPartyCreate(lua_State* L) { // Party(userdata) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 2); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Party> party = player->getParty(); + auto party = player->getParty(); if (!party) { party = Party::create(player); g_game().updatePlayerShield(player); player->sendCreatureSkull(player); - pushUserdata<Party>(L, party); - setMetatable(L, -1, "Party"); + Lua::pushUserdata<Party>(L, party); + Lua::setMetatable(L, -1, "Party"); } else { lua_pushnil(L); } @@ -35,12 +57,12 @@ int32_t PartyFunctions::luaPartyCreate(lua_State* L) { int PartyFunctions::luaPartyDisband(lua_State* L) { // party:disband() - std::shared_ptr<Party>* partyPtr = getRawUserDataShared<Party>(L, 1); + auto* partyPtr = Lua::getRawUserDataShared<Party>(L, 1); if (partyPtr && *partyPtr) { std::shared_ptr<Party> &party = *partyPtr; party->disband(); party = nullptr; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -49,16 +71,16 @@ int PartyFunctions::luaPartyDisband(lua_State* L) { int PartyFunctions::luaPartyGetLeader(lua_State* L) { // party:getLeader() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (!party) { lua_pushnil(L); return 1; } - std::shared_ptr<Player> leader = party->getLeader(); + const auto &leader = party->getLeader(); if (leader) { - pushUserdata<Player>(L, leader); - setMetatable(L, -1, "Player"); + Lua::pushUserdata<Player>(L, leader); + Lua::setMetatable(L, -1, "Player"); } else { lua_pushnil(L); } @@ -67,15 +89,15 @@ int PartyFunctions::luaPartyGetLeader(lua_State* L) { int PartyFunctions::luaPartySetLeader(lua_State* L) { // party:setLeader(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { - pushBoolean(L, party->passPartyLeadership(player)); + Lua::pushBoolean(L, party->passPartyLeadership(player)); } else { lua_pushnil(L); } @@ -84,7 +106,7 @@ int PartyFunctions::luaPartySetLeader(lua_State* L) { int PartyFunctions::luaPartyGetMembers(lua_State* L) { // party:getMembers() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (!party) { lua_pushnil(L); return 1; @@ -92,9 +114,9 @@ int PartyFunctions::luaPartyGetMembers(lua_State* L) { int index = 0; lua_createtable(L, party->getMemberCount(), 0); - for (std::shared_ptr<Player> player : party->getMembers()) { - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + for (const auto &player : party->getMembers()) { + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; @@ -102,7 +124,7 @@ int PartyFunctions::luaPartyGetMembers(lua_State* L) { int PartyFunctions::luaPartyGetMemberCount(lua_State* L) { // party:getMemberCount() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { lua_pushnumber(L, party->getMemberCount()); } else { @@ -113,14 +135,14 @@ int PartyFunctions::luaPartyGetMemberCount(lua_State* L) { int PartyFunctions::luaPartyGetInvitees(lua_State* L) { // party:getInvitees() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { lua_createtable(L, party->getInvitationCount(), 0); int index = 0; - for (std::shared_ptr<Player> player : party->getInvitees()) { - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + for (const auto &player : party->getInvitees()) { + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } } else { @@ -131,7 +153,7 @@ int PartyFunctions::luaPartyGetInvitees(lua_State* L) { int PartyFunctions::luaPartyGetInviteeCount(lua_State* L) { // party:getInviteeCount() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { lua_pushnumber(L, party->getInvitationCount()); } else { @@ -142,15 +164,15 @@ int PartyFunctions::luaPartyGetInviteeCount(lua_State* L) { int PartyFunctions::luaPartyAddInvite(lua_State* L) { // party:addInvite(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party && player) { - pushBoolean(L, party->invitePlayer(player)); + Lua::pushBoolean(L, party->invitePlayer(player)); } else { lua_pushnil(L); } @@ -159,15 +181,15 @@ int PartyFunctions::luaPartyAddInvite(lua_State* L) { int PartyFunctions::luaPartyRemoveInvite(lua_State* L) { // party:removeInvite(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party && player) { - pushBoolean(L, party->removeInvite(player)); + Lua::pushBoolean(L, party->removeInvite(player)); } else { lua_pushnil(L); } @@ -176,15 +198,15 @@ int PartyFunctions::luaPartyRemoveInvite(lua_State* L) { int PartyFunctions::luaPartyAddMember(lua_State* L) { // party:addMember(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party && player) { - pushBoolean(L, party->joinParty(player)); + Lua::pushBoolean(L, party->joinParty(player)); } else { lua_pushnil(L); } @@ -193,15 +215,15 @@ int PartyFunctions::luaPartyAddMember(lua_State* L) { int PartyFunctions::luaPartyRemoveMember(lua_State* L) { // party:removeMember(player) - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party && player) { - pushBoolean(L, party->leaveParty(player)); + Lua::pushBoolean(L, party->leaveParty(player)); } else { lua_pushnil(L); } @@ -210,9 +232,9 @@ int PartyFunctions::luaPartyRemoveMember(lua_State* L) { int PartyFunctions::luaPartyIsSharedExperienceActive(lua_State* L) { // party:isSharedExperienceActive() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { - pushBoolean(L, party->isSharedExperienceActive()); + Lua::pushBoolean(L, party->isSharedExperienceActive()); } else { lua_pushnil(L); } @@ -221,9 +243,9 @@ int PartyFunctions::luaPartyIsSharedExperienceActive(lua_State* L) { int PartyFunctions::luaPartyIsSharedExperienceEnabled(lua_State* L) { // party:isSharedExperienceEnabled() - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { - pushBoolean(L, party->isSharedExperienceEnabled()); + Lua::pushBoolean(L, party->isSharedExperienceEnabled()); } else { lua_pushnil(L); } @@ -232,11 +254,11 @@ int PartyFunctions::luaPartyIsSharedExperienceEnabled(lua_State* L) { int PartyFunctions::luaPartyShareExperience(lua_State* L) { // party:shareExperience(experience) - uint64_t experience = getNumber<uint64_t>(L, 2); - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const uint64_t experience = Lua::getNumber<uint64_t>(L, 2); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { party->shareExperience(experience); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -245,10 +267,10 @@ int PartyFunctions::luaPartyShareExperience(lua_State* L) { int PartyFunctions::luaPartySetSharedExperience(lua_State* L) { // party:setSharedExperience(active) - bool active = getBoolean(L, 2); - std::shared_ptr<Party> party = getUserdataShared<Party>(L, 1); + const bool active = Lua::getBoolean(L, 2); + const auto &party = Lua::getUserdataShared<Party>(L, 1); if (party) { - pushBoolean(L, party->setSharedExperience(party->getLeader(), active)); + Lua::pushBoolean(L, party->setSharedExperience(party->getLeader(), active)); } else { lua_pushnil(L); } diff --git a/src/lua/functions/creatures/player/party_functions.hpp b/src/lua/functions/creatures/player/party_functions.hpp index 312a39952fe..52801e349d6 100644 --- a/src/lua/functions/creatures/player/party_functions.hpp +++ b/src/lua/functions/creatures/player/party_functions.hpp @@ -9,29 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class PartyFunctions final : LuaScriptInterface { +class PartyFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Party", "", PartyFunctions::luaPartyCreate); - registerMetaMethod(L, "Party", "__eq", PartyFunctions::luaUserdataCompare); - registerMethod(L, "Party", "disband", PartyFunctions::luaPartyDisband); - registerMethod(L, "Party", "getLeader", PartyFunctions::luaPartyGetLeader); - registerMethod(L, "Party", "setLeader", PartyFunctions::luaPartySetLeader); - registerMethod(L, "Party", "getMembers", PartyFunctions::luaPartyGetMembers); - registerMethod(L, "Party", "getMemberCount", PartyFunctions::luaPartyGetMemberCount); - registerMethod(L, "Party", "getInvitees", PartyFunctions::luaPartyGetInvitees); - registerMethod(L, "Party", "getInviteeCount", PartyFunctions::luaPartyGetInviteeCount); - registerMethod(L, "Party", "addInvite", PartyFunctions::luaPartyAddInvite); - registerMethod(L, "Party", "removeInvite", PartyFunctions::luaPartyRemoveInvite); - registerMethod(L, "Party", "addMember", PartyFunctions::luaPartyAddMember); - registerMethod(L, "Party", "removeMember", PartyFunctions::luaPartyRemoveMember); - registerMethod(L, "Party", "isSharedExperienceActive", PartyFunctions::luaPartyIsSharedExperienceActive); - registerMethod(L, "Party", "isSharedExperienceEnabled", PartyFunctions::luaPartyIsSharedExperienceEnabled); - registerMethod(L, "Party", "shareExperience", PartyFunctions::luaPartyShareExperience); - registerMethod(L, "Party", "setSharedExperience", PartyFunctions::luaPartySetSharedExperience); - } + static void init(lua_State* L); private: static int luaPartyCreate(lua_State* L); diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index cbb0a18afd7..08045f1de00 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -9,109 +9,489 @@ #include "lua/functions/creatures/player/player_functions.hpp" +#include "account/account.hpp" +#include "creatures/appearance/mounts/mounts.hpp" #include "creatures/combat/spells.hpp" #include "creatures/creature.hpp" #include "creatures/interactions/chat.hpp" -#include "creatures/players/player.hpp" -#include "creatures/players/wheel/player_wheel.hpp" +#include "creatures/monsters/monsters.hpp" #include "creatures/players/achievement/player_achievement.hpp" -#include "creatures/players/cyclopedia/player_badge.hpp" #include "creatures/players/cyclopedia/player_cyclopedia.hpp" #include "creatures/players/cyclopedia/player_title.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/vip/player_vip.hpp" +#include "creatures/players/vocations/vocation.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "server/network/protocol/protocolgame.hpp" #include "game/game.hpp" +#include "game/scheduling/save_manager.hpp" +#include "io/iobestiary.hpp" #include "io/iologindata.hpp" #include "io/ioprey.hpp" +#include "items/containers/depot/depotchest.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "items/containers/rewards/reward.hpp" #include "items/item.hpp" -#include "game/scheduling/save_manager.hpp" -#include "game/scheduling/dispatcher.hpp" #include "map/spectators.hpp" +#include "kv/kv.hpp" -#include "enums/account_errors.hpp" -#include "enums/account_type.hpp" #include "enums/account_coins.hpp" +#include "enums/account_errors.hpp" +#include "enums/player_icons.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void PlayerFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Player", "Creature", PlayerFunctions::luaPlayerCreate); + Lua::registerMetaMethod(L, "Player", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Player", "resetCharmsBestiary", PlayerFunctions::luaPlayerResetCharmsMonsters); + Lua::registerMethod(L, "Player", "unlockAllCharmRunes", PlayerFunctions::luaPlayerUnlockAllCharmRunes); + Lua::registerMethod(L, "Player", "addCharmPoints", PlayerFunctions::luaPlayeraddCharmPoints); + Lua::registerMethod(L, "Player", "isPlayer", PlayerFunctions::luaPlayerIsPlayer); + + Lua::registerMethod(L, "Player", "getGuid", PlayerFunctions::luaPlayerGetGuid); + Lua::registerMethod(L, "Player", "getIp", PlayerFunctions::luaPlayerGetIp); + Lua::registerMethod(L, "Player", "getAccountId", PlayerFunctions::luaPlayerGetAccountId); + Lua::registerMethod(L, "Player", "getLastLoginSaved", PlayerFunctions::luaPlayerGetLastLoginSaved); + Lua::registerMethod(L, "Player", "getLastLogout", PlayerFunctions::luaPlayerGetLastLogout); + + Lua::registerMethod(L, "Player", "getAccountType", PlayerFunctions::luaPlayerGetAccountType); + Lua::registerMethod(L, "Player", "setAccountType", PlayerFunctions::luaPlayerSetAccountType); + + Lua::registerMethod(L, "Player", "isMonsterBestiaryUnlocked", PlayerFunctions::luaPlayerIsMonsterBestiaryUnlocked); + Lua::registerMethod(L, "Player", "addBestiaryKill", PlayerFunctions::luaPlayerAddBestiaryKill); + Lua::registerMethod(L, "Player", "charmExpansion", PlayerFunctions::luaPlayercharmExpansion); + Lua::registerMethod(L, "Player", "getCharmMonsterType", PlayerFunctions::luaPlayergetCharmMonsterType); + + Lua::registerMethod(L, "Player", "isMonsterPrey", PlayerFunctions::luaPlayerisMonsterPrey); + Lua::registerMethod(L, "Player", "getPreyCards", PlayerFunctions::luaPlayerGetPreyCards); + Lua::registerMethod(L, "Player", "getPreyLootPercentage", PlayerFunctions::luaPlayerGetPreyLootPercentage); + Lua::registerMethod(L, "Player", "getPreyExperiencePercentage", PlayerFunctions::luaPlayerGetPreyExperiencePercentage); + Lua::registerMethod(L, "Player", "preyThirdSlot", PlayerFunctions::luaPlayerPreyThirdSlot); + Lua::registerMethod(L, "Player", "taskHuntingThirdSlot", PlayerFunctions::luaPlayerTaskThirdSlot); + Lua::registerMethod(L, "Player", "removePreyStamina", PlayerFunctions::luaPlayerRemovePreyStamina); + Lua::registerMethod(L, "Player", "addPreyCards", PlayerFunctions::luaPlayerAddPreyCards); + Lua::registerMethod(L, "Player", "removeTaskHuntingPoints", PlayerFunctions::luaPlayerRemoveTaskHuntingPoints); + Lua::registerMethod(L, "Player", "getTaskHuntingPoints", PlayerFunctions::luaPlayerGetTaskHuntingPoints); + Lua::registerMethod(L, "Player", "addTaskHuntingPoints", PlayerFunctions::luaPlayerAddTaskHuntingPoints); + + Lua::registerMethod(L, "Player", "getCapacity", PlayerFunctions::luaPlayerGetCapacity); + Lua::registerMethod(L, "Player", "setCapacity", PlayerFunctions::luaPlayerSetCapacity); + + Lua::registerMethod(L, "Player", "isTraining", PlayerFunctions::luaPlayerGetIsTraining); + Lua::registerMethod(L, "Player", "setTraining", PlayerFunctions::luaPlayerSetTraining); + + Lua::registerMethod(L, "Player", "getFreeCapacity", PlayerFunctions::luaPlayerGetFreeCapacity); + + Lua::registerMethod(L, "Player", "getKills", PlayerFunctions::luaPlayerGetKills); + Lua::registerMethod(L, "Player", "setKills", PlayerFunctions::luaPlayerSetKills); + + Lua::registerMethod(L, "Player", "getReward", PlayerFunctions::luaPlayerGetReward); + Lua::registerMethod(L, "Player", "removeReward", PlayerFunctions::luaPlayerRemoveReward); + Lua::registerMethod(L, "Player", "getRewardList", PlayerFunctions::luaPlayerGetRewardList); + + Lua::registerMethod(L, "Player", "setDailyReward", PlayerFunctions::luaPlayerSetDailyReward); + + Lua::registerMethod(L, "Player", "sendInventory", PlayerFunctions::luaPlayerSendInventory); + Lua::registerMethod(L, "Player", "sendLootStats", PlayerFunctions::luaPlayerSendLootStats); + Lua::registerMethod(L, "Player", "updateSupplyTracker", PlayerFunctions::luaPlayerUpdateSupplyTracker); + Lua::registerMethod(L, "Player", "updateKillTracker", PlayerFunctions::luaPlayerUpdateKillTracker); + + Lua::registerMethod(L, "Player", "getDepotLocker", PlayerFunctions::luaPlayerGetDepotLocker); + Lua::registerMethod(L, "Player", "getDepotChest", PlayerFunctions::luaPlayerGetDepotChest); + Lua::registerMethod(L, "Player", "getInbox", PlayerFunctions::luaPlayerGetInbox); + + Lua::registerMethod(L, "Player", "getSkullTime", PlayerFunctions::luaPlayerGetSkullTime); + Lua::registerMethod(L, "Player", "setSkullTime", PlayerFunctions::luaPlayerSetSkullTime); + Lua::registerMethod(L, "Player", "getDeathPenalty", PlayerFunctions::luaPlayerGetDeathPenalty); + + Lua::registerMethod(L, "Player", "getExperience", PlayerFunctions::luaPlayerGetExperience); + Lua::registerMethod(L, "Player", "addExperience", PlayerFunctions::luaPlayerAddExperience); + Lua::registerMethod(L, "Player", "removeExperience", PlayerFunctions::luaPlayerRemoveExperience); + Lua::registerMethod(L, "Player", "getLevel", PlayerFunctions::luaPlayerGetLevel); + + Lua::registerMethod(L, "Player", "getMagicShieldCapacityFlat", PlayerFunctions::luaPlayerGetMagicShieldCapacityFlat); + Lua::registerMethod(L, "Player", "getMagicShieldCapacityPercent", PlayerFunctions::luaPlayerGetMagicShieldCapacityPercent); + + Lua::registerMethod(L, "Player", "sendSpellCooldown", PlayerFunctions::luaPlayerSendSpellCooldown); + Lua::registerMethod(L, "Player", "sendSpellGroupCooldown", PlayerFunctions::luaPlayerSendSpellGroupCooldown); + + Lua::registerMethod(L, "Player", "getMagicLevel", PlayerFunctions::luaPlayerGetMagicLevel); + Lua::registerMethod(L, "Player", "getBaseMagicLevel", PlayerFunctions::luaPlayerGetBaseMagicLevel); + Lua::registerMethod(L, "Player", "getMana", PlayerFunctions::luaPlayerGetMana); + Lua::registerMethod(L, "Player", "addMana", PlayerFunctions::luaPlayerAddMana); + Lua::registerMethod(L, "Player", "getMaxMana", PlayerFunctions::luaPlayerGetMaxMana); + Lua::registerMethod(L, "Player", "setMaxMana", PlayerFunctions::luaPlayerSetMaxMana); + Lua::registerMethod(L, "Player", "getManaSpent", PlayerFunctions::luaPlayerGetManaSpent); + Lua::registerMethod(L, "Player", "addManaSpent", PlayerFunctions::luaPlayerAddManaSpent); + + Lua::registerMethod(L, "Player", "getBaseMaxHealth", PlayerFunctions::luaPlayerGetBaseMaxHealth); + Lua::registerMethod(L, "Player", "getBaseMaxMana", PlayerFunctions::luaPlayerGetBaseMaxMana); + + Lua::registerMethod(L, "Player", "getSkillLevel", PlayerFunctions::luaPlayerGetSkillLevel); + Lua::registerMethod(L, "Player", "getEffectiveSkillLevel", PlayerFunctions::luaPlayerGetEffectiveSkillLevel); + Lua::registerMethod(L, "Player", "getSkillPercent", PlayerFunctions::luaPlayerGetSkillPercent); + Lua::registerMethod(L, "Player", "getSkillTries", PlayerFunctions::luaPlayerGetSkillTries); + Lua::registerMethod(L, "Player", "addSkillTries", PlayerFunctions::luaPlayerAddSkillTries); + + Lua::registerMethod(L, "Player", "setLevel", PlayerFunctions::luaPlayerSetLevel); + Lua::registerMethod(L, "Player", "setMagicLevel", PlayerFunctions::luaPlayerSetMagicLevel); + Lua::registerMethod(L, "Player", "setSkillLevel", PlayerFunctions::luaPlayerSetSkillLevel); + + Lua::registerMethod(L, "Player", "addOfflineTrainingTime", PlayerFunctions::luaPlayerAddOfflineTrainingTime); + Lua::registerMethod(L, "Player", "getOfflineTrainingTime", PlayerFunctions::luaPlayerGetOfflineTrainingTime); + Lua::registerMethod(L, "Player", "removeOfflineTrainingTime", PlayerFunctions::luaPlayerRemoveOfflineTrainingTime); + + Lua::registerMethod(L, "Player", "addOfflineTrainingTries", PlayerFunctions::luaPlayerAddOfflineTrainingTries); + + Lua::registerMethod(L, "Player", "getOfflineTrainingSkill", PlayerFunctions::luaPlayerGetOfflineTrainingSkill); + Lua::registerMethod(L, "Player", "setOfflineTrainingSkill", PlayerFunctions::luaPlayerSetOfflineTrainingSkill); + + Lua::registerMethod(L, "Player", "getItemCount", PlayerFunctions::luaPlayerGetItemCount); + Lua::registerMethod(L, "Player", "getStashItemCount", PlayerFunctions::luaPlayerGetStashItemCount); + Lua::registerMethod(L, "Player", "getItemById", PlayerFunctions::luaPlayerGetItemById); + + Lua::registerMethod(L, "Player", "getVocation", PlayerFunctions::luaPlayerGetVocation); + Lua::registerMethod(L, "Player", "setVocation", PlayerFunctions::luaPlayerSetVocation); + Lua::registerMethod(L, "Player", "isPromoted", PlayerFunctions::luaPlayerIsPromoted); + + Lua::registerMethod(L, "Player", "getSex", PlayerFunctions::luaPlayerGetSex); + Lua::registerMethod(L, "Player", "setSex", PlayerFunctions::luaPlayerSetSex); + + Lua::registerMethod(L, "Player", "getPronoun", PlayerFunctions::luaPlayerGetPronoun); + Lua::registerMethod(L, "Player", "setPronoun", PlayerFunctions::luaPlayerSetPronoun); + + Lua::registerMethod(L, "Player", "getTown", PlayerFunctions::luaPlayerGetTown); + Lua::registerMethod(L, "Player", "setTown", PlayerFunctions::luaPlayerSetTown); + + Lua::registerMethod(L, "Player", "getGuild", PlayerFunctions::luaPlayerGetGuild); + Lua::registerMethod(L, "Player", "setGuild", PlayerFunctions::luaPlayerSetGuild); + + Lua::registerMethod(L, "Player", "getGuildLevel", PlayerFunctions::luaPlayerGetGuildLevel); + Lua::registerMethod(L, "Player", "setGuildLevel", PlayerFunctions::luaPlayerSetGuildLevel); + + Lua::registerMethod(L, "Player", "getGuildNick", PlayerFunctions::luaPlayerGetGuildNick); + Lua::registerMethod(L, "Player", "setGuildNick", PlayerFunctions::luaPlayerSetGuildNick); + + Lua::registerMethod(L, "Player", "getGroup", PlayerFunctions::luaPlayerGetGroup); + Lua::registerMethod(L, "Player", "setGroup", PlayerFunctions::luaPlayerSetGroup); + + Lua::registerMethod(L, "Player", "setSpecialContainersAvailable", PlayerFunctions::luaPlayerSetSpecialContainersAvailable); + Lua::registerMethod(L, "Player", "getStashCount", PlayerFunctions::luaPlayerGetStashCounter); + Lua::registerMethod(L, "Player", "openStash", PlayerFunctions::luaPlayerOpenStash); + + Lua::registerMethod(L, "Player", "getStamina", PlayerFunctions::luaPlayerGetStamina); + Lua::registerMethod(L, "Player", "setStamina", PlayerFunctions::luaPlayerSetStamina); + + Lua::registerMethod(L, "Player", "getSoul", PlayerFunctions::luaPlayerGetSoul); + Lua::registerMethod(L, "Player", "addSoul", PlayerFunctions::luaPlayerAddSoul); + Lua::registerMethod(L, "Player", "getMaxSoul", PlayerFunctions::luaPlayerGetMaxSoul); + + Lua::registerMethod(L, "Player", "getBankBalance", PlayerFunctions::luaPlayerGetBankBalance); + Lua::registerMethod(L, "Player", "setBankBalance", PlayerFunctions::luaPlayerSetBankBalance); + + Lua::registerMethod(L, "Player", "getStorageValue", PlayerFunctions::luaPlayerGetStorageValue); + Lua::registerMethod(L, "Player", "setStorageValue", PlayerFunctions::luaPlayerSetStorageValue); + + Lua::registerMethod(L, "Player", "getStorageValueByName", PlayerFunctions::luaPlayerGetStorageValueByName); + Lua::registerMethod(L, "Player", "setStorageValueByName", PlayerFunctions::luaPlayerSetStorageValueByName); + + Lua::registerMethod(L, "Player", "addItem", PlayerFunctions::luaPlayerAddItem); + Lua::registerMethod(L, "Player", "addItemEx", PlayerFunctions::luaPlayerAddItemEx); + Lua::registerMethod(L, "Player", "addItemStash", PlayerFunctions::luaPlayerAddItemStash); + Lua::registerMethod(L, "Player", "removeStashItem", PlayerFunctions::luaPlayerRemoveStashItem); + Lua::registerMethod(L, "Player", "removeItem", PlayerFunctions::luaPlayerRemoveItem); + Lua::registerMethod(L, "Player", "sendContainer", PlayerFunctions::luaPlayerSendContainer); + Lua::registerMethod(L, "Player", "sendUpdateContainer", PlayerFunctions::luaPlayerSendUpdateContainer); + + Lua::registerMethod(L, "Player", "getMoney", PlayerFunctions::luaPlayerGetMoney); + Lua::registerMethod(L, "Player", "addMoney", PlayerFunctions::luaPlayerAddMoney); + Lua::registerMethod(L, "Player", "removeMoney", PlayerFunctions::luaPlayerRemoveMoney); + + Lua::registerMethod(L, "Player", "showTextDialog", PlayerFunctions::luaPlayerShowTextDialog); + + Lua::registerMethod(L, "Player", "sendTextMessage", PlayerFunctions::luaPlayerSendTextMessage); + Lua::registerMethod(L, "Player", "sendChannelMessage", PlayerFunctions::luaPlayerSendChannelMessage); + Lua::registerMethod(L, "Player", "sendPrivateMessage", PlayerFunctions::luaPlayerSendPrivateMessage); + Lua::registerMethod(L, "Player", "channelSay", PlayerFunctions::luaPlayerChannelSay); + Lua::registerMethod(L, "Player", "openChannel", PlayerFunctions::luaPlayerOpenChannel); + + Lua::registerMethod(L, "Player", "getSlotItem", PlayerFunctions::luaPlayerGetSlotItem); + + Lua::registerMethod(L, "Player", "getParty", PlayerFunctions::luaPlayerGetParty); + + Lua::registerMethod(L, "Player", "addOutfit", PlayerFunctions::luaPlayerAddOutfit); + Lua::registerMethod(L, "Player", "addOutfitAddon", PlayerFunctions::luaPlayerAddOutfitAddon); + Lua::registerMethod(L, "Player", "removeOutfit", PlayerFunctions::luaPlayerRemoveOutfit); + Lua::registerMethod(L, "Player", "removeOutfitAddon", PlayerFunctions::luaPlayerRemoveOutfitAddon); + Lua::registerMethod(L, "Player", "hasOutfit", PlayerFunctions::luaPlayerHasOutfit); + Lua::registerMethod(L, "Player", "sendOutfitWindow", PlayerFunctions::luaPlayerSendOutfitWindow); + + Lua::registerMethod(L, "Player", "addMount", PlayerFunctions::luaPlayerAddMount); + Lua::registerMethod(L, "Player", "removeMount", PlayerFunctions::luaPlayerRemoveMount); + Lua::registerMethod(L, "Player", "hasMount", PlayerFunctions::luaPlayerHasMount); + + Lua::registerMethod(L, "Player", "addFamiliar", PlayerFunctions::luaPlayerAddFamiliar); + Lua::registerMethod(L, "Player", "removeFamiliar", PlayerFunctions::luaPlayerRemoveFamiliar); + Lua::registerMethod(L, "Player", "hasFamiliar", PlayerFunctions::luaPlayerHasFamiliar); + Lua::registerMethod(L, "Player", "setFamiliarLooktype", PlayerFunctions::luaPlayerSetFamiliarLooktype); + Lua::registerMethod(L, "Player", "getFamiliarLooktype", PlayerFunctions::luaPlayerGetFamiliarLooktype); + + Lua::registerMethod(L, "Player", "getPremiumDays", PlayerFunctions::luaPlayerGetPremiumDays); + Lua::registerMethod(L, "Player", "addPremiumDays", PlayerFunctions::luaPlayerAddPremiumDays); + Lua::registerMethod(L, "Player", "removePremiumDays", PlayerFunctions::luaPlayerRemovePremiumDays); + + Lua::registerMethod(L, "Player", "getTibiaCoins", PlayerFunctions::luaPlayerGetTibiaCoins); + Lua::registerMethod(L, "Player", "addTibiaCoins", PlayerFunctions::luaPlayerAddTibiaCoins); + Lua::registerMethod(L, "Player", "removeTibiaCoins", PlayerFunctions::luaPlayerRemoveTibiaCoins); + + Lua::registerMethod(L, "Player", "getTransferableCoins", PlayerFunctions::luaPlayerGetTransferableCoins); + Lua::registerMethod(L, "Player", "addTransferableCoins", PlayerFunctions::luaPlayerAddTransferableCoins); + Lua::registerMethod(L, "Player", "removeTransferableCoins", PlayerFunctions::luaPlayerRemoveTransferableCoins); + + Lua::registerMethod(L, "Player", "sendBlessStatus", PlayerFunctions::luaPlayerSendBlessStatus); + Lua::registerMethod(L, "Player", "hasBlessing", PlayerFunctions::luaPlayerHasBlessing); + Lua::registerMethod(L, "Player", "addBlessing", PlayerFunctions::luaPlayerAddBlessing); + Lua::registerMethod(L, "Player", "removeBlessing", PlayerFunctions::luaPlayerRemoveBlessing); + Lua::registerMethod(L, "Player", "getBlessingCount", PlayerFunctions::luaPlayerGetBlessingCount); + + Lua::registerMethod(L, "Player", "canLearnSpell", PlayerFunctions::luaPlayerCanLearnSpell); + Lua::registerMethod(L, "Player", "learnSpell", PlayerFunctions::luaPlayerLearnSpell); + Lua::registerMethod(L, "Player", "forgetSpell", PlayerFunctions::luaPlayerForgetSpell); + Lua::registerMethod(L, "Player", "hasLearnedSpell", PlayerFunctions::luaPlayerHasLearnedSpell); + + Lua::registerMethod(L, "Player", "openImbuementWindow", PlayerFunctions::luaPlayerOpenImbuementWindow); + Lua::registerMethod(L, "Player", "closeImbuementWindow", PlayerFunctions::luaPlayerCloseImbuementWindow); + + Lua::registerMethod(L, "Player", "sendTutorial", PlayerFunctions::luaPlayerSendTutorial); + Lua::registerMethod(L, "Player", "addMapMark", PlayerFunctions::luaPlayerAddMapMark); + + Lua::registerMethod(L, "Player", "save", PlayerFunctions::luaPlayerSave); + Lua::registerMethod(L, "Player", "popupFYI", PlayerFunctions::luaPlayerPopupFYI); + + Lua::registerMethod(L, "Player", "isPzLocked", PlayerFunctions::luaPlayerIsPzLocked); + + Lua::registerMethod(L, "Player", "getClient", PlayerFunctions::luaPlayerGetClient); + + Lua::registerMethod(L, "Player", "getHouse", PlayerFunctions::luaPlayerGetHouse); + Lua::registerMethod(L, "Player", "sendHouseWindow", PlayerFunctions::luaPlayerSendHouseWindow); + Lua::registerMethod(L, "Player", "setEditHouse", PlayerFunctions::luaPlayerSetEditHouse); + + Lua::registerMethod(L, "Player", "setGhostMode", PlayerFunctions::luaPlayerSetGhostMode); + + Lua::registerMethod(L, "Player", "getContainerId", PlayerFunctions::luaPlayerGetContainerId); + Lua::registerMethod(L, "Player", "getContainerById", PlayerFunctions::luaPlayerGetContainerById); + Lua::registerMethod(L, "Player", "getContainerIndex", PlayerFunctions::luaPlayerGetContainerIndex); + + Lua::registerMethod(L, "Player", "getInstantSpells", PlayerFunctions::luaPlayerGetInstantSpells); + Lua::registerMethod(L, "Player", "canCast", PlayerFunctions::luaPlayerCanCast); + + Lua::registerMethod(L, "Player", "hasChaseMode", PlayerFunctions::luaPlayerHasChaseMode); + Lua::registerMethod(L, "Player", "hasSecureMode", PlayerFunctions::luaPlayerHasSecureMode); + Lua::registerMethod(L, "Player", "getFightMode", PlayerFunctions::luaPlayerGetFightMode); + + Lua::registerMethod(L, "Player", "getBaseXpGain", PlayerFunctions::luaPlayerGetBaseXpGain); + Lua::registerMethod(L, "Player", "setBaseXpGain", PlayerFunctions::luaPlayerSetBaseXpGain); + Lua::registerMethod(L, "Player", "getVoucherXpBoost", PlayerFunctions::luaPlayerGetVoucherXpBoost); + Lua::registerMethod(L, "Player", "setVoucherXpBoost", PlayerFunctions::luaPlayerSetVoucherXpBoost); + Lua::registerMethod(L, "Player", "getGrindingXpBoost", PlayerFunctions::luaPlayerGetGrindingXpBoost); + Lua::registerMethod(L, "Player", "setGrindingXpBoost", PlayerFunctions::luaPlayerSetGrindingXpBoost); + Lua::registerMethod(L, "Player", "getXpBoostPercent", PlayerFunctions::luaPlayerGetXpBoostPercent); + Lua::registerMethod(L, "Player", "setXpBoostPercent", PlayerFunctions::luaPlayerSetXpBoostPercent); + Lua::registerMethod(L, "Player", "getStaminaXpBoost", PlayerFunctions::luaPlayerGetStaminaXpBoost); + Lua::registerMethod(L, "Player", "setStaminaXpBoost", PlayerFunctions::luaPlayerSetStaminaXpBoost); + Lua::registerMethod(L, "Player", "getXpBoostTime", PlayerFunctions::luaPlayerGetXpBoostTime); + Lua::registerMethod(L, "Player", "setXpBoostTime", PlayerFunctions::luaPlayerSetXpBoostTime); + + Lua::registerMethod(L, "Player", "getIdleTime", PlayerFunctions::luaPlayerGetIdleTime); + Lua::registerMethod(L, "Player", "getFreeBackpackSlots", PlayerFunctions::luaPlayerGetFreeBackpackSlots); + + Lua::registerMethod(L, "Player", "isOffline", PlayerFunctions::luaPlayerIsOffline); + + Lua::registerMethod(L, "Player", "openMarket", PlayerFunctions::luaPlayerOpenMarket); + + Lua::registerMethod(L, "Player", "instantSkillWOD", PlayerFunctions::luaPlayerInstantSkillWOD); + Lua::registerMethod(L, "Player", "upgradeSpellsWOD", PlayerFunctions::luaPlayerUpgradeSpellWOD); + Lua::registerMethod(L, "Player", "revelationStageWOD", PlayerFunctions::luaPlayerRevelationStageWOD); + Lua::registerMethod(L, "Player", "reloadData", PlayerFunctions::luaPlayerReloadData); + Lua::registerMethod(L, "Player", "onThinkWheelOfDestiny", PlayerFunctions::luaPlayerOnThinkWheelOfDestiny); + Lua::registerMethod(L, "Player", "avatarTimer", PlayerFunctions::luaPlayerAvatarTimer); + Lua::registerMethod(L, "Player", "getWheelSpellAdditionalArea", PlayerFunctions::luaPlayerGetWheelSpellAdditionalArea); + Lua::registerMethod(L, "Player", "getWheelSpellAdditionalTarget", PlayerFunctions::luaPlayerGetWheelSpellAdditionalTarget); + Lua::registerMethod(L, "Player", "getWheelSpellAdditionalDuration", PlayerFunctions::luaPlayerGetWheelSpellAdditionalDuration); + + // Forge Functions + Lua::registerMethod(L, "Player", "openForge", PlayerFunctions::luaPlayerOpenForge); + Lua::registerMethod(L, "Player", "closeForge", PlayerFunctions::luaPlayerCloseForge); + + Lua::registerMethod(L, "Player", "addForgeDusts", PlayerFunctions::luaPlayerAddForgeDusts); + Lua::registerMethod(L, "Player", "removeForgeDusts", PlayerFunctions::luaPlayerRemoveForgeDusts); + Lua::registerMethod(L, "Player", "getForgeDusts", PlayerFunctions::luaPlayerGetForgeDusts); + Lua::registerMethod(L, "Player", "setForgeDusts", PlayerFunctions::luaPlayerSetForgeDusts); + + Lua::registerMethod(L, "Player", "addForgeDustLevel", PlayerFunctions::luaPlayerAddForgeDustLevel); + Lua::registerMethod(L, "Player", "removeForgeDustLevel", PlayerFunctions::luaPlayerRemoveForgeDustLevel); + Lua::registerMethod(L, "Player", "getForgeDustLevel", PlayerFunctions::luaPlayerGetForgeDustLevel); + + Lua::registerMethod(L, "Player", "getForgeSlivers", PlayerFunctions::luaPlayerGetForgeSlivers); + Lua::registerMethod(L, "Player", "getForgeCores", PlayerFunctions::luaPlayerGetForgeCores); + Lua::registerMethod(L, "Player", "isUIExhausted", PlayerFunctions::luaPlayerIsUIExhausted); + Lua::registerMethod(L, "Player", "updateUIExhausted", PlayerFunctions::luaPlayerUpdateUIExhausted); + + Lua::registerMethod(L, "Player", "setFaction", PlayerFunctions::luaPlayerSetFaction); + Lua::registerMethod(L, "Player", "getFaction", PlayerFunctions::luaPlayerGetFaction); + + // Bosstiary Functions + Lua::registerMethod(L, "Player", "getBosstiaryLevel", PlayerFunctions::luaPlayerGetBosstiaryLevel); + Lua::registerMethod(L, "Player", "getBosstiaryKills", PlayerFunctions::luaPlayerGetBosstiaryKills); + Lua::registerMethod(L, "Player", "addBosstiaryKill", PlayerFunctions::luaPlayerAddBosstiaryKill); + Lua::registerMethod(L, "Player", "setBossPoints", PlayerFunctions::luaPlayerSetBossPoints); + Lua::registerMethod(L, "Player", "setRemoveBossTime", PlayerFunctions::luaPlayerSetRemoveBossTime); + Lua::registerMethod(L, "Player", "getSlotBossId", PlayerFunctions::luaPlayerGetSlotBossId); + Lua::registerMethod(L, "Player", "getBossBonus", PlayerFunctions::luaPlayerGetBossBonus); + Lua::registerMethod(L, "Player", "sendBosstiaryCooldownTimer", PlayerFunctions::luaPlayerBosstiaryCooldownTimer); + + Lua::registerMethod(L, "Player", "sendSingleSoundEffect", PlayerFunctions::luaPlayerSendSingleSoundEffect); + Lua::registerMethod(L, "Player", "sendDoubleSoundEffect", PlayerFunctions::luaPlayerSendDoubleSoundEffect); + + Lua::registerMethod(L, "Player", "getName", PlayerFunctions::luaPlayerGetName); + Lua::registerMethod(L, "Player", "changeName", PlayerFunctions::luaPlayerChangeName); + + Lua::registerMethod(L, "Player", "hasGroupFlag", PlayerFunctions::luaPlayerHasGroupFlag); + Lua::registerMethod(L, "Player", "setGroupFlag", PlayerFunctions::luaPlayerSetGroupFlag); + Lua::registerMethod(L, "Player", "removeGroupFlag", PlayerFunctions::luaPlayerRemoveGroupFlag); + + Lua::registerMethod(L, "Player", "setHazardSystemPoints", PlayerFunctions::luaPlayerAddHazardSystemPoints); + Lua::registerMethod(L, "Player", "getHazardSystemPoints", PlayerFunctions::luaPlayerGetHazardSystemPoints); + + Lua::registerMethod(L, "Player", "setLoyaltyBonus", PlayerFunctions::luaPlayerSetLoyaltyBonus); + Lua::registerMethod(L, "Player", "getLoyaltyBonus", PlayerFunctions::luaPlayerGetLoyaltyBonus); + Lua::registerMethod(L, "Player", "getLoyaltyPoints", PlayerFunctions::luaPlayerGetLoyaltyPoints); + Lua::registerMethod(L, "Player", "getLoyaltyTitle", PlayerFunctions::luaPlayerGetLoyaltyTitle); + Lua::registerMethod(L, "Player", "setLoyaltyTitle", PlayerFunctions::luaPlayerSetLoyaltyTitle); + + Lua::registerMethod(L, "Player", "updateConcoction", PlayerFunctions::luaPlayerUpdateConcoction); + Lua::registerMethod(L, "Player", "clearSpellCooldowns", PlayerFunctions::luaPlayerClearSpellCooldowns); + + Lua::registerMethod(L, "Player", "isVip", PlayerFunctions::luaPlayerIsVip); + Lua::registerMethod(L, "Player", "getVipDays", PlayerFunctions::luaPlayerGetVipDays); + Lua::registerMethod(L, "Player", "getVipTime", PlayerFunctions::luaPlayerGetVipTime); + + Lua::registerMethod(L, "Player", "kv", PlayerFunctions::luaPlayerKV); + Lua::registerMethod(L, "Player", "getStoreInbox", PlayerFunctions::luaPlayerGetStoreInbox); + + Lua::registerMethod(L, "Player", "hasAchievement", PlayerFunctions::luaPlayerHasAchievement); + Lua::registerMethod(L, "Player", "addAchievement", PlayerFunctions::luaPlayerAddAchievement); + Lua::registerMethod(L, "Player", "removeAchievement", PlayerFunctions::luaPlayerRemoveAchievement); + Lua::registerMethod(L, "Player", "getAchievementPoints", PlayerFunctions::luaPlayerGetAchievementPoints); + Lua::registerMethod(L, "Player", "addAchievementPoints", PlayerFunctions::luaPlayerAddAchievementPoints); + Lua::registerMethod(L, "Player", "removeAchievementPoints", PlayerFunctions::luaPlayerRemoveAchievementPoints); + + // Badge Functions + Lua::registerMethod(L, "Player", "addBadge", PlayerFunctions::luaPlayerAddBadge); + + // Title Functions + Lua::registerMethod(L, "Player", "addTitle", PlayerFunctions::luaPlayerAddTitle); + Lua::registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles); + Lua::registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle); + + // Store Summary + Lua::registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary); + + Lua::registerMethod(L, "Player", "takeScreenshot", PlayerFunctions::luaPlayerTakeScreenshot); + Lua::registerMethod(L, "Player", "sendIconBakragore", PlayerFunctions::luaPlayerSendIconBakragore); + Lua::registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore); + Lua::registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear); + + GroupFunctions::init(L); + GuildFunctions::init(L); + MountFunctions::init(L); + PartyFunctions::init(L); + VocationFunctions::init(L); +} int PlayerFunctions::luaPlayerSendInventory(lua_State* L) { // player:sendInventory() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } player->sendInventoryIds(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendLootStats(lua_State* L) { // player:sendLootStats(item, count) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { lua_pushnil(L); return 1; } - uint8_t count = getNumber<uint8_t>(L, 3, 0); + const auto count = Lua::getNumber<uint8_t>(L, 3, 0); if (count == 0) { lua_pushnil(L); return 1; } player->sendLootStats(item, count); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerUpdateSupplyTracker(lua_State* L) { // player:updateSupplyTracker(item) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { lua_pushnil(L); return 1; } player->updateSupplyTracker(item); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerUpdateKillTracker(lua_State* L) { // player:updateKillTracker(creature, corpse) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> monster = getUserdataShared<Creature>(L, 2); + const auto &monster = Lua::getUserdataShared<Creature>(L, 2); if (!monster) { lua_pushnil(L); return 1; } - std::shared_ptr<Container> corpse = getUserdataShared<Container>(L, 3); + const auto &corpse = Lua::getUserdataShared<Container>(L, 3); if (!corpse) { lua_pushnil(L); return 1; } player->updateKillTracker(corpse, monster->getName(), monster->getCurrentOutfit()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -120,33 +500,33 @@ int PlayerFunctions::luaPlayerUpdateKillTracker(lua_State* L) { int PlayerFunctions::luaPlayerCreate(lua_State* L) { // Player(id or guid or name or userdata) std::shared_ptr<Player> player; - if (isNumber(L, 2)) { - uint32_t id = getNumber<uint32_t>(L, 2); + if (Lua::isNumber(L, 2)) { + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); if (id >= Player::getFirstID() && id <= Player::getLastID()) { player = g_game().getPlayerByID(id); } else { player = g_game().getPlayerByGUID(id); } - } else if (isString(L, 2)) { - ReturnValue ret = g_game().getPlayerByNameWildcard(getString(L, 2), player); + } else if (Lua::isString(L, 2)) { + ReturnValue ret = g_game().getPlayerByNameWildcard(Lua::getString(L, 2), player); if (ret != RETURNVALUE_NOERROR) { lua_pushnil(L); lua_pushnumber(L, ret); return 2; } - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_t::Player) { + } else if (Lua::isUserdata(L, 2)) { + if (Lua::getUserdataType(L, 2) != LuaData_t::Player) { lua_pushnil(L); return 1; } - player = getUserdataShared<Player>(L, 2); + player = Lua::getUserdataShared<Player>(L, 2); } else { player = nullptr; } if (player) { - pushUserdata<Player>(L, player); - setMetatable(L, -1, "Player"); + Lua::pushUserdata<Player>(L, player); + Lua::setMetatable(L, -1, "Player"); } else { lua_pushnil(L); } @@ -155,7 +535,7 @@ int PlayerFunctions::luaPlayerCreate(lua_State* L) { int PlayerFunctions::luaPlayerResetCharmsMonsters(lua_State* L) { // player:resetCharmsBestiary() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->setCharmPoints(0); player->setCharmExpansion(false); @@ -164,7 +544,7 @@ int PlayerFunctions::luaPlayerResetCharmsMonsters(lua_State* L) { for (int8_t i = CHARM_WOUND; i <= CHARM_LAST; i++) { player->parseRacebyCharm(static_cast<charmRune_t>(i), true, 0); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -173,16 +553,16 @@ int PlayerFunctions::luaPlayerResetCharmsMonsters(lua_State* L) { int PlayerFunctions::luaPlayerUnlockAllCharmRunes(lua_State* L) { // player:unlockAllCharmRunes() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { for (int8_t i = CHARM_WOUND; i <= CHARM_LAST; i++) { const auto charm = g_iobestiary().getBestiaryCharm(static_cast<charmRune_t>(i)); if (charm) { - int32_t value = g_iobestiary().bitToggle(player->getUnlockedRunesBit(), charm, true); + const int32_t value = g_iobestiary().bitToggle(player->getUnlockedRunesBit(), charm, true); player->setUnlockedRunesBit(value); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -191,16 +571,16 @@ int PlayerFunctions::luaPlayerUnlockAllCharmRunes(lua_State* L) { int PlayerFunctions::luaPlayeraddCharmPoints(lua_State* L) { // player:addCharmPoints() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int16_t charms = getNumber<int16_t>(L, 2); + int16_t charms = Lua::getNumber<int16_t>(L, 2); if (charms >= 0) { g_iobestiary().addCharmPoints(player, static_cast<uint16_t>(charms)); } else { charms = -charms; g_iobestiary().addCharmPoints(player, static_cast<uint16_t>(charms), true); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -209,13 +589,13 @@ int PlayerFunctions::luaPlayeraddCharmPoints(lua_State* L) { int PlayerFunctions::luaPlayerIsPlayer(lua_State* L) { // player:isPlayer() - pushBoolean(L, getUserdataShared<Player>(L, 1) != nullptr); + Lua::pushBoolean(L, Lua::getUserdataShared<Player>(L, 1) != nullptr); return 1; } int PlayerFunctions::luaPlayerGetGuid(lua_State* L) { // player:getGuid() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getGUID()); } else { @@ -226,7 +606,7 @@ int PlayerFunctions::luaPlayerGetGuid(lua_State* L) { int PlayerFunctions::luaPlayerGetIp(lua_State* L) { // player:getIp() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getIP()); } else { @@ -237,7 +617,7 @@ int PlayerFunctions::luaPlayerGetIp(lua_State* L) { int PlayerFunctions::luaPlayerGetAccountId(lua_State* L) { // player:getAccountId() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || player->getAccountId() == 0) { lua_pushnil(L); return 1; @@ -250,7 +630,7 @@ int PlayerFunctions::luaPlayerGetAccountId(lua_State* L) { int PlayerFunctions::luaPlayerGetLastLoginSaved(lua_State* L) { // player:getLastLoginSaved() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getLastLoginSaved()); } else { @@ -261,7 +641,7 @@ int PlayerFunctions::luaPlayerGetLastLoginSaved(lua_State* L) { int PlayerFunctions::luaPlayerGetLastLogout(lua_State* L) { // player:getLastLogout() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getLastLogout()); } else { @@ -272,7 +652,7 @@ int PlayerFunctions::luaPlayerGetLastLogout(lua_State* L) { int PlayerFunctions::luaPlayerGetAccountType(lua_State* L) { // player:getAccountType() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getAccountType()); } else { @@ -283,34 +663,34 @@ int PlayerFunctions::luaPlayerGetAccountType(lua_State* L) { int PlayerFunctions::luaPlayerSetAccountType(lua_State* L) { // player:setAccountType(accountType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { lua_pushnil(L); return 1; } - if (player->getAccount()->setAccountType(getNumber<uint8_t>(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->setAccountType(Lua::getNumber<AccountType>(L, 2)) != AccountErrors_t::Ok) { lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddBestiaryKill(lua_State* L) { // player:addBestiaryKill(name[, amount = 1]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const auto mtype = g_monsters().getMonsterType(getString(L, 2)); + const auto &mtype = g_monsters().getMonsterType(Lua::getString(L, 2)); if (mtype) { - g_iobestiary().addBestiaryKill(player, mtype, getNumber<uint32_t>(L, 3, 1)); - pushBoolean(L, true); + g_iobestiary().addBestiaryKill(player, mtype, Lua::getNumber<uint32_t>(L, 3, 1)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -322,42 +702,42 @@ int PlayerFunctions::luaPlayerAddBestiaryKill(lua_State* L) { int PlayerFunctions::luaPlayerIsMonsterBestiaryUnlocked(lua_State* L) { // player:isMonsterBestiaryUnlocked(raceId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player == nullptr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - auto raceId = getNumber<uint16_t>(L, 2, 0); + const auto raceId = Lua::getNumber<uint16_t>(L, 2, 0); if (!g_monsters().getMonsterTypeByRaceId(raceId)) { - reportErrorFunc("Monster race id not exists"); - pushBoolean(L, false); + Lua::reportErrorFunc("Monster race id not exists"); + Lua::pushBoolean(L, false); return 0; } - for (uint16_t finishedRaceId : g_iobestiary().getBestiaryFinished(player)) { + for (const uint16_t finishedRaceId : g_iobestiary().getBestiaryFinished(player)) { if (raceId == finishedRaceId) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } } - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 0; } int PlayerFunctions::luaPlayergetCharmMonsterType(lua_State* L) { // player:getCharmMonsterType(charmRune_t) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - charmRune_t charmid = getNumber<charmRune_t>(L, 2); - uint16_t raceid = player->parseRacebyCharm(charmid, false, 0); + const charmRune_t charmid = Lua::getNumber<charmRune_t>(L, 2); + const uint16_t raceid = player->parseRacebyCharm(charmid, false, 0); if (raceid > 0) { - const auto mtype = g_monsters().getMonsterTypeByRaceId(raceid); + const auto &mtype = g_monsters().getMonsterTypeByRaceId(raceid); if (mtype) { - pushUserdata<MonsterType>(L, mtype); - setMetatable(L, -1, "MonsterType"); + Lua::pushUserdata<MonsterType>(L, mtype); + Lua::setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } @@ -372,10 +752,10 @@ int PlayerFunctions::luaPlayergetCharmMonsterType(lua_State* L) { int PlayerFunctions::luaPlayerRemovePreyStamina(lua_State* L) { // player:removePreyStamina(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - g_ioprey().checkPlayerPreys(player, getNumber<uint8_t>(L, 2, 1)); - pushBoolean(L, true); + g_ioprey().checkPlayerPreys(player, Lua::getNumber<uint8_t>(L, 2, 1)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -384,9 +764,9 @@ int PlayerFunctions::luaPlayerRemovePreyStamina(lua_State* L) { int PlayerFunctions::luaPlayerAddPreyCards(lua_State* L) { // player:addPreyCards(amount) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - player->addPreyCards(getNumber<uint64_t>(L, 2, 0)); - pushBoolean(L, true); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + player->addPreyCards(Lua::getNumber<uint64_t>(L, 2, 0)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -395,7 +775,7 @@ int PlayerFunctions::luaPlayerAddPreyCards(lua_State* L) { int PlayerFunctions::luaPlayerGetPreyCards(lua_State* L) { // player:getPreyCards() - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { lua_pushnumber(L, static_cast<lua_Number>(player->getPreyCards())); } else { lua_pushnil(L); @@ -405,8 +785,8 @@ int PlayerFunctions::luaPlayerGetPreyCards(lua_State* L) { int PlayerFunctions::luaPlayerGetPreyExperiencePercentage(lua_State* L) { // player:getPreyExperiencePercentage(raceId) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(getNumber<uint16_t>(L, 2, 0)); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(Lua::getNumber<uint16_t>(L, 2, 0)); slot && slot->isOccupied() && slot->bonus == PreyBonus_Experience && slot->bonusTimeLeft > 0) { lua_pushnumber(L, static_cast<lua_Number>(100 + slot->bonusPercentage)); } else { @@ -420,8 +800,8 @@ int PlayerFunctions::luaPlayerGetPreyExperiencePercentage(lua_State* L) { int PlayerFunctions::luaPlayerRemoveTaskHuntingPoints(lua_State* L) { // player:removeTaskHuntingPoints(amount) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - pushBoolean(L, player->useTaskHuntingPoints(getNumber<uint64_t>(L, 2, 0))); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + Lua::pushBoolean(L, player->useTaskHuntingPoints(Lua::getNumber<uint64_t>(L, 2, 0))); } else { lua_pushnil(L); } @@ -430,10 +810,10 @@ int PlayerFunctions::luaPlayerRemoveTaskHuntingPoints(lua_State* L) { int PlayerFunctions::luaPlayerGetTaskHuntingPoints(lua_State* L) { // player:getTaskHuntingPoints() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player == nullptr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -443,9 +823,9 @@ int PlayerFunctions::luaPlayerGetTaskHuntingPoints(lua_State* L) { int PlayerFunctions::luaPlayerAddTaskHuntingPoints(lua_State* L) { // player:addTaskHuntingPoints(amount) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - auto points = getNumber<uint64_t>(L, 2); - player->addTaskHuntingPoints(getNumber<uint64_t>(L, 2)); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + const auto points = Lua::getNumber<uint64_t>(L, 2); + player->addTaskHuntingPoints(Lua::getNumber<uint64_t>(L, 2)); lua_pushnumber(L, static_cast<lua_Number>(points)); } else { lua_pushnil(L); @@ -455,8 +835,8 @@ int PlayerFunctions::luaPlayerAddTaskHuntingPoints(lua_State* L) { int PlayerFunctions::luaPlayerGetPreyLootPercentage(lua_State* L) { // player:getPreyLootPercentage(raceid) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(getNumber<uint16_t>(L, 2, 0)); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(Lua::getNumber<uint16_t>(L, 2, 0)); slot && slot->isOccupied() && slot->bonus == PreyBonus_Loot) { lua_pushnumber(L, slot->bonusPercentage); } else { @@ -470,12 +850,12 @@ int PlayerFunctions::luaPlayerGetPreyLootPercentage(lua_State* L) { int PlayerFunctions::luaPlayerisMonsterPrey(lua_State* L) { // player:isMonsterPrey(raceid) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1)) { - if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(getNumber<uint16_t>(L, 2, 0)); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1)) { + if (const std::unique_ptr<PreySlot> &slot = player->getPreyWithMonster(Lua::getNumber<uint16_t>(L, 2, 0)); slot && slot->isOccupied()) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } } else { lua_pushnil(L); @@ -485,14 +865,14 @@ int PlayerFunctions::luaPlayerisMonsterPrey(lua_State* L) { int PlayerFunctions::luaPlayerPreyThirdSlot(lua_State* L) { // get: player:preyThirdSlot() set: player:preyThirdSlot(bool) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1); const auto &slot = player->getPreySlotById(PreySlot_Three)) { if (!slot) { lua_pushnil(L); } else if (lua_gettop(L) == 1) { - pushBoolean(L, slot->state != PreyDataState_Locked); + Lua::pushBoolean(L, slot->state != PreyDataState_Locked); } else { - if (getBoolean(L, 2, false)) { + if (Lua::getBoolean(L, 2, false)) { slot->eraseBonus(); slot->state = PreyDataState_Selection; slot->reloadMonsterGrid(player->getPreyBlackList(), player->getLevel()); @@ -501,7 +881,7 @@ int PlayerFunctions::luaPlayerPreyThirdSlot(lua_State* L) { slot->state = PreyDataState_Locked; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -512,12 +892,12 @@ int PlayerFunctions::luaPlayerPreyThirdSlot(lua_State* L) { int PlayerFunctions::luaPlayerTaskThirdSlot(lua_State* L) { // get: player:taskHuntingThirdSlot() set: player:taskHuntingThirdSlot(bool) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1); const auto &slot = player->getTaskHuntingSlotById(PreySlot_Three)) { if (lua_gettop(L) == 1) { - pushBoolean(L, slot->state != PreyTaskDataState_Locked); + Lua::pushBoolean(L, slot->state != PreyTaskDataState_Locked); } else { - if (getBoolean(L, 2, false)) { + if (Lua::getBoolean(L, 2, false)) { slot->eraseTask(); slot->reloadReward(); slot->state = PreyTaskDataState_Selection; @@ -527,7 +907,7 @@ int PlayerFunctions::luaPlayerTaskThirdSlot(lua_State* L) { slot->state = PreyTaskDataState_Locked; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -537,13 +917,13 @@ int PlayerFunctions::luaPlayerTaskThirdSlot(lua_State* L) { int PlayerFunctions::luaPlayercharmExpansion(lua_State* L) { // get: player:charmExpansion() set: player:charmExpansion(bool) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { if (lua_gettop(L) == 1) { - pushBoolean(L, player->hasCharmExpansion()); + Lua::pushBoolean(L, player->hasCharmExpansion()); } else { - player->setCharmExpansion(getBoolean(L, 2, false)); - pushBoolean(L, true); + player->setCharmExpansion(Lua::getBoolean(L, 2, false)); + Lua::pushBoolean(L, true); } } else { lua_pushnil(L); @@ -553,7 +933,7 @@ int PlayerFunctions::luaPlayercharmExpansion(lua_State* L) { int PlayerFunctions::luaPlayerGetCapacity(lua_State* L) { // player:getCapacity() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getCapacity()); } else { @@ -564,11 +944,11 @@ int PlayerFunctions::luaPlayerGetCapacity(lua_State* L) { int PlayerFunctions::luaPlayerSetCapacity(lua_State* L) { // player:setCapacity(capacity) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->capacity = getNumber<uint32_t>(L, 2); + player->capacity = Lua::getNumber<uint32_t>(L, 2); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -577,11 +957,11 @@ int PlayerFunctions::luaPlayerSetCapacity(lua_State* L) { int PlayerFunctions::luaPlayerSetTraining(lua_State* L) { // player:setTraining(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - bool value = getBoolean(L, 2, false); + const bool value = Lua::getBoolean(L, 2, false); player->setTraining(value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -590,10 +970,10 @@ int PlayerFunctions::luaPlayerSetTraining(lua_State* L) { int PlayerFunctions::luaPlayerGetIsTraining(lua_State* L) { // player:isTraining() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } @@ -603,7 +983,7 @@ int PlayerFunctions::luaPlayerGetIsTraining(lua_State* L) { int PlayerFunctions::luaPlayerGetFreeCapacity(lua_State* L) { // player:getFreeCapacity() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getFreeCapacity()); } else { @@ -614,7 +994,7 @@ int PlayerFunctions::luaPlayerGetFreeCapacity(lua_State* L) { int PlayerFunctions::luaPlayerGetKills(lua_State* L) { // player:getKills() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -628,7 +1008,7 @@ int PlayerFunctions::luaPlayerGetKills(lua_State* L) { lua_rawseti(L, -2, 1); lua_pushnumber(L, kill.time); lua_rawseti(L, -2, 2); - pushBoolean(L, kill.unavenged); + Lua::pushBoolean(L, kill.unavenged); lua_rawseti(L, -2, 3); lua_rawseti(L, -2, ++idx); } @@ -638,7 +1018,7 @@ int PlayerFunctions::luaPlayerGetKills(lua_State* L) { int PlayerFunctions::luaPlayerSetKills(lua_State* L) { // player:setKills(kills) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -654,52 +1034,52 @@ int PlayerFunctions::luaPlayerSetKills(lua_State* L) { lua_rawgeti(L, -1, 1); // push target lua_rawgeti(L, -2, 2); // push time lua_rawgeti(L, -3, 3); // push unavenged - newKills.emplace_back(luaL_checknumber(L, -3), luaL_checknumber(L, -2), getBoolean(L, -1)); + newKills.emplace_back(luaL_checknumber(L, -3), luaL_checknumber(L, -2), Lua::getBoolean(L, -1)); lua_pop(L, 4); } player->unjustifiedKills = std::move(newKills); player->sendUnjustifiedPoints(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetReward(lua_State* L) { // player:getReward(rewardId[, autoCreate = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint64_t rewardId = getNumber<uint64_t>(L, 2); - bool autoCreate = getBoolean(L, 3, false); - if (auto reward = player->getReward(rewardId, autoCreate)) { - pushUserdata<Item>(L, reward); - setItemMetatable(L, -1, reward); + const uint64_t rewardId = Lua::getNumber<uint64_t>(L, 2); + const bool autoCreate = Lua::getBoolean(L, 3, false); + if (const auto &reward = player->getReward(rewardId, autoCreate)) { + Lua::pushUserdata<Item>(L, reward); + Lua::setItemMetatable(L, -1, reward); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PlayerFunctions::luaPlayerRemoveReward(lua_State* L) { // player:removeReward(rewardId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint32_t rewardId = getNumber<uint32_t>(L, 2); + const uint32_t rewardId = Lua::getNumber<uint32_t>(L, 2); player->removeReward(rewardId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetRewardList(lua_State* L) { // player:getRewardList() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -719,10 +1099,10 @@ int PlayerFunctions::luaPlayerGetRewardList(lua_State* L) { int PlayerFunctions::luaPlayerSetDailyReward(lua_State* L) { // player:setDailyReward(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setDailyReward(getNumber<uint8_t>(L, 2)); - pushBoolean(L, true); + player->setDailyReward(Lua::getNumber<uint8_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -731,29 +1111,29 @@ int PlayerFunctions::luaPlayerSetDailyReward(lua_State* L) { int PlayerFunctions::luaPlayerGetDepotLocker(lua_State* L) { // player:getDepotLocker(depotId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint32_t depotId = getNumber<uint32_t>(L, 2); - std::shared_ptr<DepotLocker> depotLocker = player->getDepotLocker(depotId); + const uint32_t depotId = Lua::getNumber<uint32_t>(L, 2); + const auto &depotLocker = player->getDepotLocker(depotId); if (depotLocker) { depotLocker->setParent(player); - pushUserdata<Item>(L, depotLocker); - setItemMetatable(L, -1, depotLocker); + Lua::pushUserdata<Item>(L, depotLocker); + Lua::setItemMetatable(L, -1, depotLocker); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PlayerFunctions::luaPlayerGetStashCounter(lua_State* L) { // player:getStashCount() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t sizeStash = getStashSize(player->getStashItems()); + const uint16_t sizeStash = getStashSize(player->getStashItems()); lua_pushnumber(L, sizeStash); } else { lua_pushnil(L); @@ -763,46 +1143,46 @@ int PlayerFunctions::luaPlayerGetStashCounter(lua_State* L) { int PlayerFunctions::luaPlayerGetDepotChest(lua_State* L) { // player:getDepotChest(depotId[, autoCreate = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint32_t depotId = getNumber<uint32_t>(L, 2); - bool autoCreate = getBoolean(L, 3, false); - std::shared_ptr<DepotChest> depotChest = player->getDepotChest(depotId, autoCreate); + const uint32_t depotId = Lua::getNumber<uint32_t>(L, 2); + const bool autoCreate = Lua::getBoolean(L, 3, false); + const auto &depotChest = player->getDepotChest(depotId, autoCreate); if (depotChest) { player->setLastDepotId(depotId); - pushUserdata<Item>(L, depotChest); - setItemMetatable(L, -1, depotChest); + Lua::pushUserdata<Item>(L, depotChest); + Lua::setItemMetatable(L, -1, depotChest); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PlayerFunctions::luaPlayerGetInbox(lua_State* L) { // player:getInbox() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Inbox> inbox = player->getInbox(); + const auto &inbox = player->getInbox(); if (inbox) { - pushUserdata<Item>(L, inbox); - setItemMetatable(L, -1, inbox); + Lua::pushUserdata<Item>(L, inbox); + Lua::setItemMetatable(L, -1, inbox); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PlayerFunctions::luaPlayerGetSkullTime(lua_State* L) { // player:getSkullTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getSkullTicks()); } else { @@ -813,10 +1193,10 @@ int PlayerFunctions::luaPlayerGetSkullTime(lua_State* L) { int PlayerFunctions::luaPlayerSetSkullTime(lua_State* L) { // player:setSkullTime(skullTime) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setSkullTicks(getNumber<int64_t>(L, 2)); - pushBoolean(L, true); + player->setSkullTicks(Lua::getNumber<int64_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -825,7 +1205,7 @@ int PlayerFunctions::luaPlayerSetSkullTime(lua_State* L) { int PlayerFunctions::luaPlayerGetDeathPenalty(lua_State* L) { // player:getDeathPenalty() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, static_cast<uint32_t>(player->getLostPercent() * 100)); } else { @@ -836,7 +1216,7 @@ int PlayerFunctions::luaPlayerGetDeathPenalty(lua_State* L) { int PlayerFunctions::luaPlayerGetExperience(lua_State* L) { // player:getExperience() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getExperience()); } else { @@ -847,12 +1227,12 @@ int PlayerFunctions::luaPlayerGetExperience(lua_State* L) { int PlayerFunctions::luaPlayerAddExperience(lua_State* L) { // player:addExperience(experience[, sendText = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int64_t experience = getNumber<int64_t>(L, 2); - bool sendText = getBoolean(L, 3, false); + const int64_t experience = Lua::getNumber<int64_t>(L, 2); + const bool sendText = Lua::getBoolean(L, 3, false); player->addExperience(nullptr, experience, sendText); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -861,12 +1241,12 @@ int PlayerFunctions::luaPlayerAddExperience(lua_State* L) { int PlayerFunctions::luaPlayerRemoveExperience(lua_State* L) { // player:removeExperience(experience[, sendText = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int64_t experience = getNumber<int64_t>(L, 2); - bool sendText = getBoolean(L, 3, false); + const int64_t experience = Lua::getNumber<int64_t>(L, 2); + const bool sendText = Lua::getBoolean(L, 3, false); player->removeExperience(experience, sendText); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -875,7 +1255,7 @@ int PlayerFunctions::luaPlayerRemoveExperience(lua_State* L) { int PlayerFunctions::luaPlayerGetLevel(lua_State* L) { // player:getLevel() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getLevel()); } else { @@ -886,9 +1266,9 @@ int PlayerFunctions::luaPlayerGetLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetMagicShieldCapacityFlat(lua_State* L) { // player:getMagicShieldCapacityFlat(useCharges) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - lua_pushnumber(L, player->getMagicShieldCapacityFlat(getBoolean(L, 2, false))); + lua_pushnumber(L, player->getMagicShieldCapacityFlat(Lua::getBoolean(L, 2, false))); } else { lua_pushnil(L); } @@ -897,9 +1277,9 @@ int PlayerFunctions::luaPlayerGetMagicShieldCapacityFlat(lua_State* L) { int PlayerFunctions::luaPlayerGetMagicShieldCapacityPercent(lua_State* L) { // player:getMagicShieldCapacityPercent(useCharges) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - lua_pushnumber(L, player->getMagicShieldCapacityPercent(getBoolean(L, 2, false))); + lua_pushnumber(L, player->getMagicShieldCapacityPercent(Lua::getBoolean(L, 2, false))); } else { lua_pushnil(L); } @@ -908,39 +1288,39 @@ int PlayerFunctions::luaPlayerGetMagicShieldCapacityPercent(lua_State* L) { int PlayerFunctions::luaPlayerSendSpellCooldown(lua_State* L) { // player:sendSpellCooldown(spellId, time) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint8_t spellId = getNumber<uint32_t>(L, 2, 1); - uint32_t time = getNumber<uint32_t>(L, 3, 0); + const uint8_t spellId = Lua::getNumber<uint32_t>(L, 2, 1); + const auto time = Lua::getNumber<uint32_t>(L, 3, 0); player->sendSpellCooldown(spellId, time); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendSpellGroupCooldown(lua_State* L) { // player:sendSpellGroupCooldown(groupId, time) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - SpellGroup_t groupId = getNumber<SpellGroup_t>(L, 2, SPELLGROUP_ATTACK); - uint32_t time = getNumber<uint32_t>(L, 3, 0); + const auto groupId = Lua::getNumber<SpellGroup_t>(L, 2, SPELLGROUP_ATTACK); + const auto time = Lua::getNumber<uint32_t>(L, 3, 0); player->sendSpellGroupCooldown(groupId, time); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetMagicLevel(lua_State* L) { // player:getMagicLevel() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getMagicLevel()); } else { @@ -951,7 +1331,7 @@ int PlayerFunctions::luaPlayerGetMagicLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetBaseMagicLevel(lua_State* L) { // player:getBaseMagicLevel() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getBaseMagicLevel()); } else { @@ -962,7 +1342,7 @@ int PlayerFunctions::luaPlayerGetBaseMagicLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetMana(lua_State* L) { // player:getMana() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getMana()); } else { @@ -973,14 +1353,14 @@ int PlayerFunctions::luaPlayerGetMana(lua_State* L) { int PlayerFunctions::luaPlayerAddMana(lua_State* L) { // player:addMana(manaChange[, animationOnLoss = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - int32_t manaChange = getNumber<int32_t>(L, 2); - bool animationOnLoss = getBoolean(L, 3, false); + const int32_t manaChange = Lua::getNumber<int32_t>(L, 2); + const bool animationOnLoss = Lua::getBoolean(L, 3, false); if (!animationOnLoss && manaChange < 0) { player->changeMana(manaChange); } else { @@ -989,13 +1369,13 @@ int PlayerFunctions::luaPlayerAddMana(lua_State* L) { damage.origin = ORIGIN_NONE; g_game().combatChangeMana(nullptr, player, damage); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetMaxMana(lua_State* L) { // player:getMaxMana() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getMaxMana()); } else { @@ -1006,23 +1386,23 @@ int PlayerFunctions::luaPlayerGetMaxMana(lua_State* L) { int PlayerFunctions::luaPlayerSetMaxMana(lua_State* L) { // player:setMaxMana(maxMana) - const auto &player = getPlayer(L, 1); + const auto &player = Lua::getPlayer(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - player->manaMax = getNumber<int32_t>(L, 2); + player->manaMax = Lua::getNumber<int32_t>(L, 2); player->mana = std::min<int32_t>(player->mana, player->manaMax); g_game().addPlayerMana(player); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetManaSpent(lua_State* L) { // player:getManaSpent() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getSpentMana()); } else { @@ -1033,10 +1413,10 @@ int PlayerFunctions::luaPlayerGetManaSpent(lua_State* L) { int PlayerFunctions::luaPlayerAddManaSpent(lua_State* L) { // player:addManaSpent(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->addManaSpent(getNumber<uint64_t>(L, 2)); - pushBoolean(L, true); + player->addManaSpent(Lua::getNumber<uint64_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1045,7 +1425,7 @@ int PlayerFunctions::luaPlayerAddManaSpent(lua_State* L) { int PlayerFunctions::luaPlayerGetBaseMaxHealth(lua_State* L) { // player:getBaseMaxHealth() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->healthMax); } else { @@ -1056,7 +1436,7 @@ int PlayerFunctions::luaPlayerGetBaseMaxHealth(lua_State* L) { int PlayerFunctions::luaPlayerGetBaseMaxMana(lua_State* L) { // player:getBaseMaxMana() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->manaMax); } else { @@ -1067,8 +1447,8 @@ int PlayerFunctions::luaPlayerGetBaseMaxMana(lua_State* L) { int PlayerFunctions::luaPlayerGetSkillLevel(lua_State* L) { // player:getSkillLevel(skillType) - skills_t skillType = getNumber<skills_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].level); } else { @@ -1079,8 +1459,8 @@ int PlayerFunctions::luaPlayerGetSkillLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetEffectiveSkillLevel(lua_State* L) { // player:getEffectiveSkillLevel(skillType) - skills_t skillType = getNumber<skills_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->getSkillLevel(skillType)); } else { @@ -1091,8 +1471,8 @@ int PlayerFunctions::luaPlayerGetEffectiveSkillLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetSkillPercent(lua_State* L) { // player:getSkillPercent(skillType) - skills_t skillType = getNumber<skills_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].percent); } else { @@ -1103,8 +1483,8 @@ int PlayerFunctions::luaPlayerGetSkillPercent(lua_State* L) { int PlayerFunctions::luaPlayerGetSkillTries(lua_State* L) { // player:getSkillTries(skillType) - skills_t skillType = getNumber<skills_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].tries); } else { @@ -1115,12 +1495,12 @@ int PlayerFunctions::luaPlayerGetSkillTries(lua_State* L) { int PlayerFunctions::luaPlayerAddSkillTries(lua_State* L) { // player:addSkillTries(skillType, tries) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - skills_t skillType = getNumber<skills_t>(L, 2); - uint64_t tries = getNumber<uint64_t>(L, 3); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const uint64_t tries = Lua::getNumber<uint64_t>(L, 3); player->addSkillAdvance(skillType, tries); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1129,14 +1509,14 @@ int PlayerFunctions::luaPlayerAddSkillTries(lua_State* L) { int PlayerFunctions::luaPlayerSetLevel(lua_State* L) { // player:setLevel(level) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t level = getNumber<uint16_t>(L, 2); + const uint16_t level = Lua::getNumber<uint16_t>(L, 2); player->level = level; player->experience = Player::getExpForLevel(level); player->sendStats(); player->sendSkills(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1145,13 +1525,13 @@ int PlayerFunctions::luaPlayerSetLevel(lua_State* L) { int PlayerFunctions::luaPlayerSetMagicLevel(lua_State* L) { // player:setMagicLevel(level[, manaSpent]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t level = getNumber<uint16_t>(L, 2); + const uint16_t level = Lua::getNumber<uint16_t>(L, 2); player->magLevel = level; - if (getNumber<uint64_t>(L, 3, 0) > 0) { - uint64_t manaSpent = getNumber<uint64_t>(L, 3); - uint64_t nextReqMana = player->vocation->getReqMana(level + 1); + if (Lua::getNumber<uint64_t>(L, 3, 0) > 0) { + const uint64_t manaSpent = Lua::getNumber<uint64_t>(L, 3); + const uint64_t nextReqMana = player->vocation->getReqMana(level + 1); player->manaSpent = manaSpent; player->magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana); } else { @@ -1160,7 +1540,7 @@ int PlayerFunctions::luaPlayerSetMagicLevel(lua_State* L) { } player->sendStats(); player->sendSkills(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1169,14 +1549,14 @@ int PlayerFunctions::luaPlayerSetMagicLevel(lua_State* L) { int PlayerFunctions::luaPlayerSetSkillLevel(lua_State* L) { // player:setSkillLevel(skillType, level[, tries]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - skills_t skillType = getNumber<skills_t>(L, 2); - uint16_t level = getNumber<uint16_t>(L, 3); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const uint16_t level = Lua::getNumber<uint16_t>(L, 3); player->skills[skillType].level = level; - if (getNumber<uint64_t>(L, 4, 0) > 0) { - uint64_t tries = getNumber<uint64_t>(L, 4); - uint64_t nextReqTries = player->vocation->getReqSkillTries(skillType, level + 1); + if (Lua::getNumber<uint64_t>(L, 4, 0) > 0) { + const uint64_t tries = Lua::getNumber<uint64_t>(L, 4); + const uint64_t nextReqTries = player->vocation->getReqSkillTries(skillType, level + 1); player->skills[skillType].tries = tries; player->skills[skillType].percent = Player::getPercentLevel(tries, nextReqTries); } else { @@ -1185,7 +1565,7 @@ int PlayerFunctions::luaPlayerSetSkillLevel(lua_State* L) { } player->sendStats(); player->sendSkills(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1194,12 +1574,12 @@ int PlayerFunctions::luaPlayerSetSkillLevel(lua_State* L) { int PlayerFunctions::luaPlayerAddOfflineTrainingTime(lua_State* L) { // player:addOfflineTrainingTime(time) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int32_t time = getNumber<int32_t>(L, 2); + const int32_t time = Lua::getNumber<int32_t>(L, 2); player->addOfflineTrainingTime(time); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1208,7 +1588,7 @@ int PlayerFunctions::luaPlayerAddOfflineTrainingTime(lua_State* L) { int PlayerFunctions::luaPlayerGetOfflineTrainingTime(lua_State* L) { // player:getOfflineTrainingTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getOfflineTrainingTime()); } else { @@ -1219,12 +1599,12 @@ int PlayerFunctions::luaPlayerGetOfflineTrainingTime(lua_State* L) { int PlayerFunctions::luaPlayerRemoveOfflineTrainingTime(lua_State* L) { // player:removeOfflineTrainingTime(time) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int32_t time = getNumber<int32_t>(L, 2); + const int32_t time = Lua::getNumber<int32_t>(L, 2); player->removeOfflineTrainingTime(time); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1233,11 +1613,11 @@ int PlayerFunctions::luaPlayerRemoveOfflineTrainingTime(lua_State* L) { int PlayerFunctions::luaPlayerAddOfflineTrainingTries(lua_State* L) { // player:addOfflineTrainingTries(skillType, tries) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - skills_t skillType = getNumber<skills_t>(L, 2); - uint64_t tries = getNumber<uint64_t>(L, 3); - pushBoolean(L, player->addOfflineTrainingTries(skillType, tries)); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const uint64_t tries = Lua::getNumber<uint64_t>(L, 3); + Lua::pushBoolean(L, player->addOfflineTrainingTries(skillType, tries)); } else { lua_pushnil(L); } @@ -1246,7 +1626,7 @@ int PlayerFunctions::luaPlayerAddOfflineTrainingTries(lua_State* L) { int PlayerFunctions::luaPlayerGetOfflineTrainingSkill(lua_State* L) { // player:getOfflineTrainingSkill() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getOfflineTrainingSkill()); } else { @@ -1257,11 +1637,11 @@ int PlayerFunctions::luaPlayerGetOfflineTrainingSkill(lua_State* L) { int PlayerFunctions::luaPlayerSetOfflineTrainingSkill(lua_State* L) { // player:setOfflineTrainingSkill(skillId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - int8_t skillId = getNumber<int8_t>(L, 2); + const int8_t skillId = Lua::getNumber<int8_t>(L, 2); player->setOfflineTrainingSkill(skillId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1270,11 +1650,11 @@ int PlayerFunctions::luaPlayerSetOfflineTrainingSkill(lua_State* L) { int PlayerFunctions::luaPlayerOpenStash(lua_State* L) { // player:openStash(isNpc) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); - bool isNpc = getBoolean(L, 2, false); + const auto &player = Lua::getUserdataShared<Player>(L, 1); + const bool isNpc = Lua::getBoolean(L, 2, false); if (player) { player->sendOpenStash(isNpc); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1284,41 +1664,41 @@ int PlayerFunctions::luaPlayerOpenStash(lua_State* L) { int PlayerFunctions::luaPlayerGetItemCount(lua_State* L) { // player:getItemCount(itemId[, subType = -1]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t subType = getNumber<int32_t>(L, 3, -1); + const auto subType = Lua::getNumber<int32_t>(L, 3, -1); lua_pushnumber(L, player->getItemTypeCount(itemId, subType)); return 1; } int PlayerFunctions::luaPlayerGetStashItemCount(lua_State* L) { // player:getStashItemCount(itemId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; @@ -1337,29 +1717,29 @@ int PlayerFunctions::luaPlayerGetStashItemCount(lua_State* L) { int PlayerFunctions::luaPlayerGetItemById(lua_State* L) { // player:getItemById(itemId, deepSearch[, subType = -1]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - bool deepSearch = getBoolean(L, 3); - int32_t subType = getNumber<int32_t>(L, 4, -1); + const bool deepSearch = Lua::getBoolean(L, 3); + const auto subType = Lua::getNumber<int32_t>(L, 4, -1); - std::shared_ptr<Item> item = g_game().findItemOfType(player, itemId, deepSearch, subType); + const auto &item = g_game().findItemOfType(player, itemId, deepSearch, subType); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -1368,10 +1748,10 @@ int PlayerFunctions::luaPlayerGetItemById(lua_State* L) { int PlayerFunctions::luaPlayerGetVocation(lua_State* L) { // player:getVocation() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushUserdata<Vocation>(L, player->getVocation()); - setMetatable(L, -1, "Vocation"); + Lua::pushUserdata<Vocation>(L, player->getVocation()); + Lua::setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } @@ -1380,25 +1760,25 @@ int PlayerFunctions::luaPlayerGetVocation(lua_State* L) { int PlayerFunctions::luaPlayerSetVocation(lua_State* L) { // player:setVocation(id or name or userdata) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } std::shared_ptr<Vocation> vocation; - if (isNumber(L, 2)) { - vocation = g_vocations().getVocation(getNumber<uint16_t>(L, 2)); - } else if (isString(L, 2)) { - vocation = g_vocations().getVocation(g_vocations().getVocationId(getString(L, 2))); - } else if (isUserdata(L, 2)) { - vocation = getUserdataShared<Vocation>(L, 2); + if (Lua::isNumber(L, 2)) { + vocation = g_vocations().getVocation(Lua::getNumber<uint16_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + vocation = g_vocations().getVocation(g_vocations().getVocationId(Lua::getString(L, 2))); + } else if (Lua::isUserdata(L, 2)) { + vocation = Lua::getUserdataShared<Vocation>(L, 2); } else { vocation = nullptr; } if (!vocation) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -1408,15 +1788,15 @@ int PlayerFunctions::luaPlayerSetVocation(lua_State* L) { player->sendBasicData(); player->wheel()->sendGiftOfLifeCooldown(); g_game().reloadCreature(player); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerIsPromoted(lua_State* L) { // player:isPromoted() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->isPromoted()); + Lua::pushBoolean(L, player->isPromoted()); } else { lua_pushnil(L); } @@ -1425,7 +1805,7 @@ int PlayerFunctions::luaPlayerIsPromoted(lua_State* L) { int PlayerFunctions::luaPlayerGetSex(lua_State* L) { // player:getSex() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getSex()); } else { @@ -1436,11 +1816,11 @@ int PlayerFunctions::luaPlayerGetSex(lua_State* L) { int PlayerFunctions::luaPlayerSetSex(lua_State* L) { // player:setSex(newSex) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - PlayerSex_t newSex = getNumber<PlayerSex_t>(L, 2); + const PlayerSex_t newSex = Lua::getNumber<PlayerSex_t>(L, 2); player->setSex(newSex); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1449,7 +1829,7 @@ int PlayerFunctions::luaPlayerSetSex(lua_State* L) { int PlayerFunctions::luaPlayerGetPronoun(lua_State* L) { // player:getPronoun() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getPronoun()); } else { @@ -1460,11 +1840,11 @@ int PlayerFunctions::luaPlayerGetPronoun(lua_State* L) { int PlayerFunctions::luaPlayerSetPronoun(lua_State* L) { // player:setPronoun(newPronoun) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - PlayerPronoun_t newPronoun = getNumber<PlayerPronoun_t>(L, 2); + const PlayerPronoun_t newPronoun = Lua::getNumber<PlayerPronoun_t>(L, 2); player->setPronoun(newPronoun); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1473,10 +1853,10 @@ int PlayerFunctions::luaPlayerSetPronoun(lua_State* L) { int PlayerFunctions::luaPlayerGetTown(lua_State* L) { // player:getTown() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushUserdata<Town>(L, player->getTown()); - setMetatable(L, -1, "Town"); + Lua::pushUserdata<Town>(L, player->getTown()); + Lua::setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } @@ -1485,16 +1865,16 @@ int PlayerFunctions::luaPlayerGetTown(lua_State* L) { int PlayerFunctions::luaPlayerSetTown(lua_State* L) { // player:setTown(town) - const auto &town = getUserdataShared<Town>(L, 2); + const auto &town = Lua::getUserdataShared<Town>(L, 2); if (!town) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->setTown(town); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1503,41 +1883,41 @@ int PlayerFunctions::luaPlayerSetTown(lua_State* L) { int PlayerFunctions::luaPlayerGetGuild(lua_State* L) { // player:getGuild() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const auto guild = player->getGuild(); + const auto &guild = player->getGuild(); if (!guild) { lua_pushnil(L); return 1; } - pushUserdata<Guild>(L, guild); - setMetatable(L, -1, "Guild"); + Lua::pushUserdata<Guild>(L, guild); + Lua::setMetatable(L, -1, "Guild"); return 1; } int PlayerFunctions::luaPlayerSetGuild(lua_State* L) { // player:setGuild(guild) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const auto guild = getUserdataShared<Guild>(L, 2); + const auto &guild = Lua::getUserdataShared<Guild>(L, 2); player->setGuild(guild); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetGuildLevel(lua_State* L) { // player:getGuildLevel() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && player->getGuild()) { lua_pushnumber(L, player->getGuildRank()->level); } else { @@ -1548,19 +1928,19 @@ int PlayerFunctions::luaPlayerGetGuildLevel(lua_State* L) { int PlayerFunctions::luaPlayerSetGuildLevel(lua_State* L) { // player:setGuildLevel(level) - uint8_t level = getNumber<uint8_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const uint8_t level = Lua::getNumber<uint8_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getGuild()) { lua_pushnil(L); return 1; } - GuildRank_ptr rank = player->getGuild()->getRankByLevel(level); + const auto &rank = player->getGuild()->getRankByLevel(level); if (!rank) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } else { player->setGuildRank(rank); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } return 1; @@ -1568,9 +1948,9 @@ int PlayerFunctions::luaPlayerSetGuildLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetGuildNick(lua_State* L) { // player:getGuildNick() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushString(L, player->getGuildNick()); + Lua::pushString(L, player->getGuildNick()); } else { lua_pushnil(L); } @@ -1579,11 +1959,11 @@ int PlayerFunctions::luaPlayerGetGuildNick(lua_State* L) { int PlayerFunctions::luaPlayerSetGuildNick(lua_State* L) { // player:setGuildNick(nick) - const std::string &nick = getString(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const std::string &nick = Lua::getString(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->setGuildNick(nick); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1592,10 +1972,10 @@ int PlayerFunctions::luaPlayerSetGuildNick(lua_State* L) { int PlayerFunctions::luaPlayerGetGroup(lua_State* L) { // player:getGroup() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushUserdata<Group>(L, player->getGroup()); - setMetatable(L, -1, "Group"); + Lua::pushUserdata<Group>(L, player->getGroup()); + Lua::setMetatable(L, -1, "Group"); } else { lua_pushnil(L); } @@ -1604,16 +1984,16 @@ int PlayerFunctions::luaPlayerGetGroup(lua_State* L) { int PlayerFunctions::luaPlayerSetGroup(lua_State* L) { // player:setGroup(group) - std::shared_ptr<Group> group = getUserdataShared<Group>(L, 2); + const auto &group = Lua::getUserdataShared<Group>(L, 2); if (!group) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->setGroup(group); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1622,13 +2002,13 @@ int PlayerFunctions::luaPlayerSetGroup(lua_State* L) { int PlayerFunctions::luaPlayerSetSpecialContainersAvailable(lua_State* L) { // player:setSpecialContainersAvailable(stashMenu, marketMenu, depotSearchMenu) - bool supplyStashMenu = getBoolean(L, 2, false); - bool marketMenu = getBoolean(L, 3, false); - bool depotSearchMenu = getBoolean(L, 4, false); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const bool supplyStashMenu = Lua::getBoolean(L, 2, false); + const bool marketMenu = Lua::getBoolean(L, 3, false); + const bool depotSearchMenu = Lua::getBoolean(L, 4, false); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->setSpecialMenuAvailable(supplyStashMenu, marketMenu, depotSearchMenu); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1637,7 +2017,7 @@ int PlayerFunctions::luaPlayerSetSpecialContainersAvailable(lua_State* L) { int PlayerFunctions::luaPlayerGetStamina(lua_State* L) { // player:getStamina() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getStaminaMinutes()); } else { @@ -1648,8 +2028,8 @@ int PlayerFunctions::luaPlayerGetStamina(lua_State* L) { int PlayerFunctions::luaPlayerSetStamina(lua_State* L) { // player:setStamina(stamina) - uint16_t stamina = getNumber<uint16_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const uint16_t stamina = Lua::getNumber<uint16_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->staminaMinutes = std::min<uint16_t>(2520, stamina); player->sendStats(); @@ -1661,7 +2041,7 @@ int PlayerFunctions::luaPlayerSetStamina(lua_State* L) { int PlayerFunctions::luaPlayerGetSoul(lua_State* L) { // player:getSoul() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getSoul()); } else { @@ -1672,11 +2052,11 @@ int PlayerFunctions::luaPlayerGetSoul(lua_State* L) { int PlayerFunctions::luaPlayerAddSoul(lua_State* L) { // player:addSoul(soulChange) - int32_t soulChange = getNumber<int32_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const int32_t soulChange = Lua::getNumber<int32_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->changeSoul(soulChange); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1685,7 +2065,7 @@ int PlayerFunctions::luaPlayerAddSoul(lua_State* L) { int PlayerFunctions::luaPlayerGetMaxSoul(lua_State* L) { // player:getMaxSoul() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && player->vocation) { lua_pushnumber(L, player->vocation->getSoulMax()); } else { @@ -1696,7 +2076,7 @@ int PlayerFunctions::luaPlayerGetMaxSoul(lua_State* L) { int PlayerFunctions::luaPlayerGetBankBalance(lua_State* L) { // player:getBankBalance() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getBankBalance()); } else { @@ -1707,51 +2087,51 @@ int PlayerFunctions::luaPlayerGetBankBalance(lua_State* L) { int PlayerFunctions::luaPlayerSetBankBalance(lua_State* L) { // player:setBankBalance(bankBalance) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - player->setBankBalance(getNumber<uint64_t>(L, 2)); - pushBoolean(L, true); + player->setBankBalance(Lua::getNumber<uint64_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetStorageValue(lua_State* L) { // player:getStorageValue(key) - const auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint32_t key = getNumber<uint32_t>(L, 2); + const uint32_t key = Lua::getNumber<uint32_t>(L, 2); lua_pushnumber(L, player->getStorageValue(key)); return 1; } int PlayerFunctions::luaPlayerSetStorageValue(lua_State* L) { // player:setStorageValue(key, value) - int32_t value = getNumber<int32_t>(L, 3); - uint32_t key = getNumber<uint32_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const int32_t value = Lua::getNumber<int32_t>(L, 3); + const uint32_t key = Lua::getNumber<uint32_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (IS_IN_KEYRANGE(key, RESERVED_RANGE)) { std::ostringstream ss; ss << "Accessing reserved range: " << key; - reportErrorFunc(ss.str()); - pushBoolean(L, false); + Lua::reportErrorFunc(ss.str()); + Lua::pushBoolean(L, false); return 1; } if (key == 0) { - reportErrorFunc("Storage key is nil"); + Lua::reportErrorFunc("Storage key is nil"); return 1; } if (player) { player->addStorageValue(key, value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -1760,68 +2140,68 @@ int PlayerFunctions::luaPlayerSetStorageValue(lua_State* L) { int PlayerFunctions::luaPlayerGetStorageValueByName(lua_State* L) { // player:getStorageValueByName(name) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } g_logger().warn("The function 'player:getStorageValueByName' is deprecated and will be removed in future versions, please use KV system"); - auto name = getString(L, 2); + const auto name = Lua::getString(L, 2); lua_pushnumber(L, player->getStorageValueByName(name)); return 1; } int PlayerFunctions::luaPlayerSetStorageValueByName(lua_State* L) { // player:setStorageValueByName(storageName, value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } g_logger().warn("The function 'player:setStorageValueByName' is deprecated and will be removed in future versions, please use KV system"); - auto storageName = getString(L, 2); - int32_t value = getNumber<int32_t>(L, 3); + const auto storageName = Lua::getString(L, 2); + const int32_t value = Lua::getNumber<int32_t>(L, 3); player->addStorageValueByName(storageName, value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddItem(lua_State* L) { // player:addItem(itemId, count = 1, canDropOnMap = true, subType = 1, slot = CONST_SLOT_WHEREEVER, tier = 0) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t count = getNumber<int32_t>(L, 3, 1); - int32_t subType = getNumber<int32_t>(L, 5, 1); + const auto count = Lua::getNumber<int32_t>(L, 3, 1); + auto subType = Lua::getNumber<int32_t>(L, 5, 1); const ItemType &it = Item::items[itemId]; int32_t itemCount = 1; - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); if (parameters >= 4) { itemCount = std::max<int32_t>(1, count); } else if (it.hasSubType()) { if (it.stackable) { - itemCount = std::ceil(count / (float_t)it.stackSize); + itemCount = std::ceil(count / static_cast<float_t>(it.stackSize)); } subType = count; @@ -1829,7 +2209,7 @@ int PlayerFunctions::luaPlayerAddItem(lua_State* L) { itemCount = std::max<int32_t>(1, count); } - bool hasTable = itemCount > 1; + const bool hasTable = itemCount > 1; if (hasTable) { lua_newtable(L); } else if (itemCount == 0) { @@ -1837,9 +2217,9 @@ int PlayerFunctions::luaPlayerAddItem(lua_State* L) { return 1; } - bool canDropOnMap = getBoolean(L, 4, true); - Slots_t slot = getNumber<Slots_t>(L, 6, CONST_SLOT_WHEREEVER); - auto tier = getNumber<uint8_t>(L, 7, 0); + const bool canDropOnMap = Lua::getBoolean(L, 4, true); + const auto slot = Lua::getNumber<Slots_t>(L, 6, CONST_SLOT_WHEREEVER); + const auto tier = Lua::getNumber<uint8_t>(L, 7, 0); for (int32_t i = 1; i <= itemCount; ++i) { int32_t stackCount = subType; if (it.stackable) { @@ -1847,7 +2227,7 @@ int PlayerFunctions::luaPlayerAddItem(lua_State* L) { subType -= stackCount; } - std::shared_ptr<Item> item = Item::CreateItem(itemId, stackCount); + const auto &item = Item::CreateItem(itemId, stackCount); if (!item) { if (!hasTable) { lua_pushnil(L); @@ -1871,12 +2251,12 @@ int PlayerFunctions::luaPlayerAddItem(lua_State* L) { if (hasTable) { lua_pushnumber(L, i); - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); lua_settable(L, -3); } else { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } } return 1; @@ -1885,33 +2265,33 @@ int PlayerFunctions::luaPlayerAddItem(lua_State* L) { int PlayerFunctions::luaPlayerAddItemEx(lua_State* L) { // player:addItemEx(item[, canDropOnMap = false[, index = INDEX_WHEREEVER[, flags = 0]]]) // player:addItemEx(item[, canDropOnMap = true[, slot = CONST_SLOT_WHEREEVER]]) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); - pushBoolean(L, false); + Lua::reportErrorFunc("Item already has a parent"); + Lua::pushBoolean(L, false); return 1; } - bool canDropOnMap = getBoolean(L, 3, false); + const bool canDropOnMap = Lua::getBoolean(L, 3, false); ReturnValue returnValue; if (canDropOnMap) { - Slots_t slot = getNumber<Slots_t>(L, 4, CONST_SLOT_WHEREEVER); + const auto slot = Lua::getNumber<Slots_t>(L, 4, CONST_SLOT_WHEREEVER); returnValue = g_game().internalPlayerAddItem(player, item, true, slot); } else { - int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER); - uint32_t flags = getNumber<uint32_t>(L, 5, 0); + const auto index = Lua::getNumber<int32_t>(L, 4, INDEX_WHEREEVER); + const auto flags = Lua::getNumber<uint32_t>(L, 5, 0); returnValue = g_game().internalAddItem(player, item, index, flags); } @@ -1924,33 +2304,33 @@ int PlayerFunctions::luaPlayerAddItemEx(lua_State* L) { int PlayerFunctions::luaPlayerAddItemStash(lua_State* L) { // player:addItemStash(itemId, count = 1) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - auto itemId = getNumber<uint16_t>(L, 2); - auto count = getNumber<uint32_t>(L, 3, 1); + const auto itemId = Lua::getNumber<uint16_t>(L, 2); + const auto count = Lua::getNumber<uint32_t>(L, 3, 1); player->addItemOnStash(itemId, count); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveStashItem(lua_State* L) { // player:removeStashItem(itemId, count) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; @@ -1963,78 +2343,78 @@ int PlayerFunctions::luaPlayerRemoveStashItem(lua_State* L) { return 1; } - uint32_t count = getNumber<uint32_t>(L, 3); - pushBoolean(L, player->withdrawItem(itemType.id, count)); + const uint32_t count = Lua::getNumber<uint32_t>(L, 3); + Lua::pushBoolean(L, player->withdrawItem(itemType.id, count)); return 1; } int PlayerFunctions::luaPlayerRemoveItem(lua_State* L) { // player:removeItem(itemId, count[, subType = -1[, ignoreEquipped = false]]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - uint32_t count = getNumber<uint32_t>(L, 3); - int32_t subType = getNumber<int32_t>(L, 4, -1); - bool ignoreEquipped = getBoolean(L, 5, false); - pushBoolean(L, player->removeItemOfType(itemId, count, subType, ignoreEquipped)); + const uint32_t count = Lua::getNumber<uint32_t>(L, 3); + const auto subType = Lua::getNumber<int32_t>(L, 4, -1); + const bool ignoreEquipped = Lua::getBoolean(L, 5, false); + Lua::pushBoolean(L, player->removeItemOfType(itemId, count, subType, ignoreEquipped)); return 1; } int PlayerFunctions::luaPlayerSendContainer(lua_State* L) { // player:sendContainer(container) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 2); + const auto &container = Lua::getUserdataShared<Container>(L, 2); if (!container) { lua_pushnil(L); return 1; } player->sendContainer(static_cast<uint8_t>(container->getID()), container, container->hasParent(), static_cast<uint8_t>(container->getFirstIndex())); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendUpdateContainer(lua_State* L) { // player:sendUpdateContainer(container) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const auto container = getUserdataShared<Container>(L, 2); + const auto &container = Lua::getUserdataShared<Container>(L, 2); if (!container) { - reportErrorFunc("Container is nullptr"); + Lua::reportErrorFunc("Container is nullptr"); return 1; } player->onSendContainer(container); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetMoney(lua_State* L) { // player:getMoney() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getMoney()); } else { @@ -2045,11 +2425,11 @@ int PlayerFunctions::luaPlayerGetMoney(lua_State* L) { int PlayerFunctions::luaPlayerAddMoney(lua_State* L) { // player:addMoney(money) - uint64_t money = getNumber<uint64_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const uint64_t money = Lua::getNumber<uint64_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { g_game().addMoney(player, money); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2058,12 +2438,12 @@ int PlayerFunctions::luaPlayerAddMoney(lua_State* L) { int PlayerFunctions::luaPlayerRemoveMoney(lua_State* L) { // player:removeMoney(money[, flags = 0[, useBank = true]]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint64_t money = getNumber<uint64_t>(L, 2); - int32_t flags = getNumber<int32_t>(L, 3, 0); - bool useBank = getBoolean(L, 4, true); - pushBoolean(L, g_game().removeMoney(player, money, flags, useBank)); + const uint64_t money = Lua::getNumber<uint64_t>(L, 2); + const auto flags = Lua::getNumber<int32_t>(L, 3, 0); + const bool useBank = Lua::getBoolean(L, 4, true); + Lua::pushBoolean(L, g_game().removeMoney(player, money, flags, useBank)); } else { lua_pushnil(L); } @@ -2072,40 +2452,40 @@ int PlayerFunctions::luaPlayerRemoveMoney(lua_State* L) { int PlayerFunctions::luaPlayerShowTextDialog(lua_State* L) { // player:showTextDialog(id or name or userdata[, text[, canWrite[, length]]]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - int32_t length = getNumber<int32_t>(L, 5, -1); - bool canWrite = getBoolean(L, 4, false); + auto length = Lua::getNumber<int32_t>(L, 5, -1); + const bool canWrite = Lua::getBoolean(L, 4, false); std::string text; - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); if (parameters >= 3) { - text = getString(L, 3); + text = Lua::getString(L, 3); } std::shared_ptr<Item> item; - if (isNumber(L, 2)) { - item = Item::CreateItem(getNumber<uint16_t>(L, 2)); - } else if (isString(L, 2)) { - item = Item::CreateItem(Item::items.getItemIdByName(getString(L, 2))); - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_t::Item) { - pushBoolean(L, false); + if (Lua::isNumber(L, 2)) { + item = Item::CreateItem(Lua::getNumber<uint16_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + item = Item::CreateItem(Item::items.getItemIdByName(Lua::getString(L, 2))); + } else if (Lua::isUserdata(L, 2)) { + if (Lua::getUserdataType(L, 2) != LuaData_t::Item) { + Lua::pushBoolean(L, false); return 1; } - item = getUserdataShared<Item>(L, 2); + item = Lua::getUserdataShared<Item>(L, 2); } else { item = nullptr; } if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -2121,7 +2501,7 @@ int PlayerFunctions::luaPlayerShowTextDialog(lua_State* L) { item->setParent(player); player->setWriteItem(item, length); player->sendTextWindow(item, length, canWrite); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -2129,99 +2509,99 @@ int PlayerFunctions::luaPlayerSendTextMessage(lua_State* L) { // player:sendTextMessage(type, text[, position, primaryValue = 0, primaryColor = TEXTCOLOR_NONE[, secondaryValue = 0, secondaryColor = TEXTCOLOR_NONE]]) // player:sendTextMessage(type, text, channelId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - int parameters = lua_gettop(L); + const int parameters = lua_gettop(L); - TextMessage message(getNumber<MessageClasses>(L, 2), getString(L, 3)); + TextMessage message(Lua::getNumber<MessageClasses>(L, 2), Lua::getString(L, 3)); if (parameters == 4) { - uint16_t channelId = getNumber<uint16_t>(L, 4); + const uint16_t channelId = Lua::getNumber<uint16_t>(L, 4); const auto &channel = g_chat().getChannel(player, channelId); if (!channel || !channel->hasUser(player)) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } message.channelId = channelId; } else { if (parameters >= 6) { - message.position = getPosition(L, 4); - message.primary.value = getNumber<int32_t>(L, 5); - message.primary.color = getNumber<TextColor_t>(L, 6); + message.position = Lua::getPosition(L, 4); + message.primary.value = Lua::getNumber<int32_t>(L, 5); + message.primary.color = Lua::getNumber<TextColor_t>(L, 6); } if (parameters >= 8) { - message.secondary.value = getNumber<int32_t>(L, 7); - message.secondary.color = getNumber<TextColor_t>(L, 8); + message.secondary.value = Lua::getNumber<int32_t>(L, 7); + message.secondary.color = Lua::getNumber<TextColor_t>(L, 8); } } player->sendTextMessage(message); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendChannelMessage(lua_State* L) { // player:sendChannelMessage(author, text, type, channelId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint16_t channelId = getNumber<uint16_t>(L, 5); - SpeakClasses type = getNumber<SpeakClasses>(L, 4); - const std::string &text = getString(L, 3); - const std::string &author = getString(L, 2); + const uint16_t channelId = Lua::getNumber<uint16_t>(L, 5); + const SpeakClasses type = Lua::getNumber<SpeakClasses>(L, 4); + const std::string &text = Lua::getString(L, 3); + const std::string &author = Lua::getString(L, 2); player->sendChannelMessage(author, text, type, channelId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendPrivateMessage(lua_State* L) { // player:sendPrivateMessage(speaker, text[, type]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Player> speaker = getUserdataShared<Player>(L, 2); - const std::string &text = getString(L, 3); - SpeakClasses type = getNumber<SpeakClasses>(L, 4, TALKTYPE_PRIVATE_FROM); + const auto &speaker = Lua::getUserdataShared<Player>(L, 2); + const std::string &text = Lua::getString(L, 3); + const auto type = Lua::getNumber<SpeakClasses>(L, 4, TALKTYPE_PRIVATE_FROM); player->sendPrivateMessage(speaker, type, text); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerChannelSay(lua_State* L) { // player:channelSay(speaker, type, text, channelId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> speaker = getCreature(L, 2); - SpeakClasses type = getNumber<SpeakClasses>(L, 3); - const std::string &text = getString(L, 4); - uint16_t channelId = getNumber<uint16_t>(L, 5); + const auto &speaker = Lua::getCreature(L, 2); + const SpeakClasses type = Lua::getNumber<SpeakClasses>(L, 3); + const std::string &text = Lua::getString(L, 4); + const uint16_t channelId = Lua::getNumber<uint16_t>(L, 5); player->sendToChannel(speaker, type, text, channelId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerOpenChannel(lua_State* L) { // player:openChannel(channelId) - uint16_t channelId = getNumber<uint16_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const uint16_t channelId = Lua::getNumber<uint16_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { g_game().playerOpenChannel(player->getID(), channelId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2230,23 +2610,23 @@ int PlayerFunctions::luaPlayerOpenChannel(lua_State* L) { int PlayerFunctions::luaPlayerGetSlotItem(lua_State* L) { // player:getSlotItem(slot) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint32_t slot = getNumber<uint32_t>(L, 2); - std::shared_ptr<Thing> thing = player->getThing(slot); + const uint32_t slot = Lua::getNumber<uint32_t>(L, 2); + const auto &thing = player->getThing(slot); if (!thing) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -2255,16 +2635,16 @@ int PlayerFunctions::luaPlayerGetSlotItem(lua_State* L) { int PlayerFunctions::luaPlayerGetParty(lua_State* L) { // player:getParty() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Party> party = player->getParty(); + const auto &party = player->getParty(); if (party) { - pushUserdata<Party>(L, party); - setMetatable(L, -1, "Party"); + Lua::pushUserdata<Party>(L, party); + Lua::setMetatable(L, -1, "Party"); } else { lua_pushnil(L); } @@ -2273,23 +2653,23 @@ int PlayerFunctions::luaPlayerGetParty(lua_State* L) { int PlayerFunctions::luaPlayerAddOutfit(lua_State* L) { // player:addOutfit(lookType or name, addon = 0) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - auto addon = getNumber<uint8_t>(L, 3, 0); + auto addon = Lua::getNumber<uint8_t>(L, 3, 0); if (lua_isnumber(L, 2)) { - player->addOutfit(getNumber<uint16_t>(L, 2), addon); + player->addOutfit(Lua::getNumber<uint16_t>(L, 2), addon); } else if (lua_isstring(L, 2)) { - const std::string &outfitName = getString(L, 2); + const std::string &outfitName = Lua::getString(L, 2); const auto &outfit = Outfits::getInstance().getOutfitByName(player->getSex(), outfitName); if (!outfit) { - reportErrorFunc("Outfit not found"); + Lua::reportErrorFunc("Outfit not found"); return 1; } player->addOutfit(outfit->lookType, addon); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2298,12 +2678,12 @@ int PlayerFunctions::luaPlayerAddOutfit(lua_State* L) { int PlayerFunctions::luaPlayerAddOutfitAddon(lua_State* L) { // player:addOutfitAddon(lookType, addon) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - uint8_t addon = getNumber<uint8_t>(L, 3); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + const uint8_t addon = Lua::getNumber<uint8_t>(L, 3); player->addOutfit(lookType, addon); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2312,10 +2692,10 @@ int PlayerFunctions::luaPlayerAddOutfitAddon(lua_State* L) { int PlayerFunctions::luaPlayerRemoveOutfit(lua_State* L) { // player:removeOutfit(lookType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - pushBoolean(L, player->removeOutfit(lookType)); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, player->removeOutfit(lookType)); } else { lua_pushnil(L); } @@ -2324,11 +2704,11 @@ int PlayerFunctions::luaPlayerRemoveOutfit(lua_State* L) { int PlayerFunctions::luaPlayerRemoveOutfitAddon(lua_State* L) { // player:removeOutfitAddon(lookType, addon) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - uint8_t addon = getNumber<uint8_t>(L, 3); - pushBoolean(L, player->removeOutfitAddon(lookType, addon)); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + const uint8_t addon = Lua::getNumber<uint8_t>(L, 3); + Lua::pushBoolean(L, player->removeOutfitAddon(lookType, addon)); } else { lua_pushnil(L); } @@ -2337,11 +2717,11 @@ int PlayerFunctions::luaPlayerRemoveOutfitAddon(lua_State* L) { int PlayerFunctions::luaPlayerHasOutfit(lua_State* L) { // player:hasOutfit(lookType[, addon = 0]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - uint8_t addon = getNumber<uint8_t>(L, 3, 0); - pushBoolean(L, player->canWear(lookType, addon)); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + const auto addon = Lua::getNumber<uint8_t>(L, 3, 0); + Lua::pushBoolean(L, player->canWear(lookType, addon)); } else { lua_pushnil(L); } @@ -2350,10 +2730,10 @@ int PlayerFunctions::luaPlayerHasOutfit(lua_State* L) { int PlayerFunctions::luaPlayerSendOutfitWindow(lua_State* L) { // player:sendOutfitWindow() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { player->sendOutfitWindow(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2362,67 +2742,67 @@ int PlayerFunctions::luaPlayerSendOutfitWindow(lua_State* L) { int PlayerFunctions::luaPlayerAddMount(lua_State* L) { // player:addMount(mountId or mountName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint8_t mountId; - if (isNumber(L, 2)) { - mountId = getNumber<uint8_t>(L, 2); + if (Lua::isNumber(L, 2)) { + mountId = Lua::getNumber<uint8_t>(L, 2); } else { - const std::shared_ptr<Mount> mount = g_game().mounts.getMountByName(getString(L, 2)); + const auto &mount = g_game().mounts->getMountByName(Lua::getString(L, 2)); if (!mount) { lua_pushnil(L); return 1; } mountId = mount->id; } - pushBoolean(L, player->tameMount(mountId)); + Lua::pushBoolean(L, player->tameMount(mountId)); return 1; } int PlayerFunctions::luaPlayerRemoveMount(lua_State* L) { // player:removeMount(mountId or mountName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } uint8_t mountId; - if (isNumber(L, 2)) { - mountId = getNumber<uint8_t>(L, 2); + if (Lua::isNumber(L, 2)) { + mountId = Lua::getNumber<uint8_t>(L, 2); } else { - const std::shared_ptr<Mount> mount = g_game().mounts.getMountByName(getString(L, 2)); + const auto &mount = g_game().mounts->getMountByName(Lua::getString(L, 2)); if (!mount) { lua_pushnil(L); return 1; } mountId = mount->id; } - pushBoolean(L, player->untameMount(mountId)); + Lua::pushBoolean(L, player->untameMount(mountId)); return 1; } int PlayerFunctions::luaPlayerHasMount(lua_State* L) { // player:hasMount(mountId or mountName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } std::shared_ptr<Mount> mount = nullptr; - if (isNumber(L, 2)) { - mount = g_game().mounts.getMountByID(getNumber<uint8_t>(L, 2)); + if (Lua::isNumber(L, 2)) { + mount = g_game().mounts->getMountByID(Lua::getNumber<uint8_t>(L, 2)); } else { - mount = g_game().mounts.getMountByName(getString(L, 2)); + mount = g_game().mounts->getMountByName(Lua::getString(L, 2)); } if (mount) { - pushBoolean(L, player->hasMount(mount)); + Lua::pushBoolean(L, player->hasMount(mount)); } else { lua_pushnil(L); } @@ -2431,10 +2811,10 @@ int PlayerFunctions::luaPlayerHasMount(lua_State* L) { int PlayerFunctions::luaPlayerAddFamiliar(lua_State* L) { // player:addFamiliar(lookType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->addFamiliar(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + player->addFamiliar(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2443,10 +2823,10 @@ int PlayerFunctions::luaPlayerAddFamiliar(lua_State* L) { int PlayerFunctions::luaPlayerRemoveFamiliar(lua_State* L) { // player:removeFamiliar(lookType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - pushBoolean(L, player->removeFamiliar(lookType)); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, player->removeFamiliar(lookType)); } else { lua_pushnil(L); } @@ -2455,10 +2835,10 @@ int PlayerFunctions::luaPlayerRemoveFamiliar(lua_State* L) { int PlayerFunctions::luaPlayerHasFamiliar(lua_State* L) { // player:hasFamiliar(lookType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t lookType = getNumber<uint16_t>(L, 2); - pushBoolean(L, player->canFamiliar(lookType)); + const uint16_t lookType = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, player->canFamiliar(lookType)); } else { lua_pushnil(L); } @@ -2467,10 +2847,10 @@ int PlayerFunctions::luaPlayerHasFamiliar(lua_State* L) { int PlayerFunctions::luaPlayerSetFamiliarLooktype(lua_State* L) { // player:setFamiliarLooktype(lookType) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setFamiliarLooktype(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + player->setFamiliarLooktype(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2479,7 +2859,7 @@ int PlayerFunctions::luaPlayerSetFamiliarLooktype(lua_State* L) { int PlayerFunctions::luaPlayerGetFamiliarLooktype(lua_State* L) { // player:getFamiliarLooktype() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->defaultOutfit.lookFamiliarsType); } else { @@ -2490,7 +2870,7 @@ int PlayerFunctions::luaPlayerGetFamiliarLooktype(lua_State* L) { int PlayerFunctions::luaPlayerGetPremiumDays(lua_State* L) { // player:getPremiumDays() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player && player->getAccount()) { lua_pushnumber(L, player->getAccount()->getPremiumRemainingDays()); } else { @@ -2501,74 +2881,74 @@ int PlayerFunctions::luaPlayerGetPremiumDays(lua_State* L) { int PlayerFunctions::luaPlayerAddPremiumDays(lua_State* L) { // player:addPremiumDays(days) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { lua_pushnil(L); return 1; } - auto premiumDays = player->getAccount()->getPremiumRemainingDays(); + const auto premiumDays = player->getAccount()->getPremiumRemainingDays(); if (premiumDays == std::numeric_limits<uint16_t>::max()) { return 1; } - int32_t addDays = std::min<int32_t>(0xFFFE - premiumDays, getNumber<uint16_t>(L, 2)); + const int32_t addDays = std::min<int32_t>(0xFFFE - premiumDays, Lua::getNumber<uint16_t>(L, 2)); if (addDays <= 0) { return 1; } player->getAccount()->addPremiumDays(addDays); - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemovePremiumDays(lua_State* L) { // player:removePremiumDays(days) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { lua_pushnil(L); return 1; } - auto premiumDays = player->getAccount()->getPremiumRemainingDays(); + const auto premiumDays = player->getAccount()->getPremiumRemainingDays(); if (premiumDays == std::numeric_limits<uint16_t>::max()) { return 1; } - int32_t removeDays = std::min<int32_t>(0xFFFE - premiumDays, getNumber<uint16_t>(L, 2)); + const int32_t removeDays = std::min<int32_t>(0xFFFE - premiumDays, Lua::getNumber<uint16_t>(L, 2)); if (removeDays <= 0) { return 1; } player->getAccount()->addPremiumDays(-removeDays); - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetTibiaCoins(lua_State* L) { // player:getTibiaCoins() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - auto [coins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Normal)); + auto [coins, result] = player->getAccount()->getCoins(CoinType::Normal); - if (result == enumToValue(AccountErrors_t::Ok)) { + if (result == AccountErrors_t::Ok) { lua_pushnumber(L, coins); } @@ -2577,67 +2957,67 @@ int PlayerFunctions::luaPlayerGetTibiaCoins(lua_State* L) { int PlayerFunctions::luaPlayerAddTibiaCoins(lua_State* L) { // player:addTibiaCoins(coins) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - if (player->account->addCoins(enumToValue(CoinType::Normal), getNumber<uint32_t>(L, 2)) != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("Failed to add coins"); + if (player->account->addCoins(CoinType::Normal, Lua::getNumber<uint32_t>(L, 2)) != AccountErrors_t::Ok) { + Lua::reportErrorFunc("Failed to add coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("Failed to save account"); + if (player->getAccount()->save() != AccountErrors_t::Ok) { + Lua::reportErrorFunc("Failed to save account"); lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveTibiaCoins(lua_State* L) { // player:removeTibiaCoins(coins) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - if (player->account->removeCoins(enumToValue(CoinType::Normal), getNumber<uint32_t>(L, 2)) != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("Failed to remove coins"); + if (player->account->removeCoins(CoinType::Normal, Lua::getNumber<uint32_t>(L, 2)) != AccountErrors_t::Ok) { + Lua::reportErrorFunc("Failed to remove coins"); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("Failed to save account"); + if (player->getAccount()->save() != AccountErrors_t::Ok) { + Lua::reportErrorFunc("Failed to save account"); lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetTransferableCoins(lua_State* L) { // player:getTransferableCoins() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - auto [coins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [coins, result] = player->getAccount()->getCoins(CoinType::Transferable); - if (result == enumToValue(AccountErrors_t::Ok)) { + if (result == AccountErrors_t::Ok) { lua_pushnumber(L, coins); } @@ -2646,62 +3026,76 @@ int PlayerFunctions::luaPlayerGetTransferableCoins(lua_State* L) { int PlayerFunctions::luaPlayerAddTransferableCoins(lua_State* L) { // player:addTransferableCoins(coins) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - if (player->account->addCoins(enumToValue(CoinType::Transferable), getNumber<uint32_t>(L, 2)) != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("failed to add transferable coins"); + if (player->account->addCoins(CoinType::Transferable, Lua::getNumber<uint32_t>(L, 2)) != AccountErrors_t::Ok) { + Lua::reportErrorFunc("failed to add transferable coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("failed to save account"); + if (player->getAccount()->save() != AccountErrors_t::Ok) { + Lua::reportErrorFunc("failed to save account"); lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveTransferableCoins(lua_State* L) { // player:removeTransferableCoins(coins) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player || !player->getAccount()) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); return 1; } - if (player->account->removeCoins(enumToValue(CoinType::Transferable), getNumber<uint32_t>(L, 2)) != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("failed to remove transferable coins"); + if (player->account->removeCoins(CoinType::Transferable, Lua::getNumber<uint32_t>(L, 2)) != AccountErrors_t::Ok) { + Lua::reportErrorFunc("failed to remove transferable coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { - reportErrorFunc("failed to save account"); + if (player->getAccount()->save() != AccountErrors_t::Ok) { + Lua::reportErrorFunc("failed to save account"); lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } +int PlayerFunctions::luaPlayerSendBlessStatus(lua_State* L) { + // player:sendBlessStatus() + const auto &player = Lua::getUserdataShared<Player>(L, 1); + if (!player) { + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + return 0; + } + + player->sendBlessStatus(); + Lua::pushBoolean(L, true); + return 1; +} + int PlayerFunctions::luaPlayerHasBlessing(lua_State* L) { // player:hasBlessing(blessing) - uint8_t blessing = getNumber<uint8_t>(L, 2); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const uint8_t blessing = Lua::getNumber<uint8_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->hasBlessing(blessing)); + Lua::pushBoolean(L, player->hasBlessing(blessing)); } else { lua_pushnil(L); } @@ -2710,52 +3104,52 @@ int PlayerFunctions::luaPlayerHasBlessing(lua_State* L) { int PlayerFunctions::luaPlayerAddBlessing(lua_State* L) { // player:addBlessing(blessing) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint8_t blessing = getNumber<uint8_t>(L, 2); - uint8_t count = getNumber<uint8_t>(L, 3); + const uint8_t blessing = Lua::getNumber<uint8_t>(L, 2); + const uint8_t count = Lua::getNumber<uint8_t>(L, 3); player->addBlessing(blessing, count); player->sendBlessStatus(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveBlessing(lua_State* L) { // player:removeBlessing(blessing) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - uint8_t blessing = getNumber<uint8_t>(L, 2); - uint8_t count = getNumber<uint8_t>(L, 3); + const uint8_t blessing = Lua::getNumber<uint8_t>(L, 2); + const uint8_t count = Lua::getNumber<uint8_t>(L, 3); if (!player->hasBlessing(blessing)) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } player->removeBlessing(blessing, count); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetBlessingCount(lua_State* L) { // player:getBlessingCount(index[, storeCount = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); - uint8_t index = getNumber<uint8_t>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); + uint8_t index = Lua::getNumber<uint8_t>(L, 2); if (index == 0) { index = 1; } if (player) { - lua_pushnumber(L, player->getBlessingCount(index, getBoolean(L, 3, false))); + lua_pushnumber(L, player->getBlessingCount(index, Lua::getBoolean(L, 3, false))); } else { lua_pushnil(L); } @@ -2764,45 +3158,45 @@ int PlayerFunctions::luaPlayerGetBlessingCount(lua_State* L) { int PlayerFunctions::luaPlayerCanLearnSpell(lua_State* L) { // player:canLearnSpell(spellName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const std::string &spellName = getString(L, 2); - const auto spell = g_spells().getInstantSpellByName(spellName); + const std::string &spellName = Lua::getString(L, 2); + const auto &spell = g_spells().getInstantSpellByName(spellName); if (!spell) { - reportErrorFunc("Spell \"" + spellName + "\" not found"); - pushBoolean(L, false); + Lua::reportErrorFunc("Spell \"" + spellName + "\" not found"); + Lua::pushBoolean(L, false); return 1; } if (player->hasFlag(PlayerFlags_t::IgnoreSpellCheck)) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } const auto vocMap = spell->getVocMap(); - if (vocMap.count(player->getVocationId()) == 0) { - pushBoolean(L, false); + if (!vocMap.contains(player->getVocationId())) { + Lua::pushBoolean(L, false); } else if (player->getLevel() < spell->getLevel()) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } else if (player->getMagicLevel() < spell->getMagicLevel()) { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } else { - pushBoolean(L, true); + Lua::pushBoolean(L, true); } return 1; } int PlayerFunctions::luaPlayerLearnSpell(lua_State* L) { // player:learnSpell(spellName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const std::string &spellName = getString(L, 2); + const std::string &spellName = Lua::getString(L, 2); player->learnInstantSpell(spellName); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2811,11 +3205,11 @@ int PlayerFunctions::luaPlayerLearnSpell(lua_State* L) { int PlayerFunctions::luaPlayerForgetSpell(lua_State* L) { // player:forgetSpell(spellName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const std::string &spellName = getString(L, 2); + const std::string &spellName = Lua::getString(L, 2); player->forgetInstantSpell(spellName); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2824,10 +3218,10 @@ int PlayerFunctions::luaPlayerForgetSpell(lua_State* L) { int PlayerFunctions::luaPlayerHasLearnedSpell(lua_State* L) { // player:hasLearnedSpell(spellName) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const std::string &spellName = getString(L, 2); - pushBoolean(L, player->hasLearnedInstantSpell(spellName)); + const std::string &spellName = Lua::getString(L, 2); + Lua::pushBoolean(L, player->hasLearnedInstantSpell(spellName)); } else { lua_pushnil(L); } @@ -2836,11 +3230,11 @@ int PlayerFunctions::luaPlayerHasLearnedSpell(lua_State* L) { int PlayerFunctions::luaPlayerSendTutorial(lua_State* L) { // player:sendTutorial(tutorialId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint8_t tutorialId = getNumber<uint8_t>(L, 2); + const uint8_t tutorialId = Lua::getNumber<uint8_t>(L, 2); player->sendTutorial(tutorialId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2849,17 +3243,17 @@ int PlayerFunctions::luaPlayerSendTutorial(lua_State* L) { int PlayerFunctions::luaPlayerOpenImbuementWindow(lua_State* L) { // player:openImbuementWindow(item) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -2869,10 +3263,10 @@ int PlayerFunctions::luaPlayerOpenImbuementWindow(lua_State* L) { int PlayerFunctions::luaPlayerCloseImbuementWindow(lua_State* L) { // player:closeImbuementWindow() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -2882,13 +3276,13 @@ int PlayerFunctions::luaPlayerCloseImbuementWindow(lua_State* L) { int PlayerFunctions::luaPlayerAddMapMark(lua_State* L) { // player:addMapMark(position, type, description) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const Position &position = getPosition(L, 2); - uint8_t type = getNumber<uint8_t>(L, 3); - const std::string &description = getString(L, 4); + const Position &position = Lua::getPosition(L, 2); + const uint8_t type = Lua::getNumber<uint8_t>(L, 3); + const std::string &description = Lua::getString(L, 4); player->sendAddMarker(position, type, description); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2897,12 +3291,12 @@ int PlayerFunctions::luaPlayerAddMapMark(lua_State* L) { int PlayerFunctions::luaPlayerSave(lua_State* L) { // player:save() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { if (!player->isOffline()) { player->loginPosition = player->getPosition(); } - pushBoolean(L, g_saveManager().savePlayer(player)); + Lua::pushBoolean(L, g_saveManager().savePlayer(player)); } else { lua_pushnil(L); } @@ -2911,11 +3305,11 @@ int PlayerFunctions::luaPlayerSave(lua_State* L) { int PlayerFunctions::luaPlayerPopupFYI(lua_State* L) { // player:popupFYI(message) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - const std::string &message = getString(L, 2); + const std::string &message = Lua::getString(L, 2); player->sendFYIBox(message); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -2924,9 +3318,9 @@ int PlayerFunctions::luaPlayerPopupFYI(lua_State* L) { int PlayerFunctions::luaPlayerIsPzLocked(lua_State* L) { // player:isPzLocked() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->isPzLocked()); + Lua::pushBoolean(L, player->isPzLocked()); } else { lua_pushnil(L); } @@ -2935,11 +3329,11 @@ int PlayerFunctions::luaPlayerIsPzLocked(lua_State* L) { int PlayerFunctions::luaPlayerGetClient(lua_State* L) { // player:getClient() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_createtable(L, 0, 2); - setField(L, "version", player->getProtocolVersion()); - setField(L, "os", player->getOperatingSystem()); + Lua::setField(L, "version", player->getProtocolVersion()); + Lua::setField(L, "os", player->getOperatingSystem()); } else { lua_pushnil(L); } @@ -2948,7 +3342,7 @@ int PlayerFunctions::luaPlayerGetClient(lua_State* L) { int PlayerFunctions::luaPlayerGetHouse(lua_State* L) { // player:getHouse() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -2956,8 +3350,8 @@ int PlayerFunctions::luaPlayerGetHouse(lua_State* L) { const auto &house = g_game().map.houses.getHouseByPlayerId(player->getGUID()); if (house) { - pushUserdata<House>(L, house); - setMetatable(L, -1, "House"); + Lua::pushUserdata<House>(L, house); + Lua::setMetatable(L, -1, "House"); } else { lua_pushnil(L); } @@ -2966,61 +3360,61 @@ int PlayerFunctions::luaPlayerGetHouse(lua_State* L) { int PlayerFunctions::luaPlayerSendHouseWindow(lua_State* L) { // player:sendHouseWindow(house, listId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const auto &house = getUserdataShared<House>(L, 2); + const auto &house = Lua::getUserdataShared<House>(L, 2); if (!house) { lua_pushnil(L); return 1; } - uint32_t listId = getNumber<uint32_t>(L, 3); + const uint32_t listId = Lua::getNumber<uint32_t>(L, 3); player->sendHouseWindow(house, listId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSetEditHouse(lua_State* L) { // player:setEditHouse(house, listId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - const auto &house = getUserdataShared<House>(L, 2); + const auto &house = Lua::getUserdataShared<House>(L, 2); if (!house) { lua_pushnil(L); return 1; } - uint32_t listId = getNumber<uint32_t>(L, 3); + const uint32_t listId = Lua::getNumber<uint32_t>(L, 3); player->setEditHouse(house, listId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSetGhostMode(lua_State* L) { // player:setGhostMode(enabled) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - bool enabled = getBoolean(L, 2); + const bool enabled = Lua::getBoolean(L, 2); if (player->isInGhostMode() == enabled) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } player->switchGhostMode(); - std::shared_ptr<Tile> tile = player->getTile(); + const auto &tile = player->getTile(); const Position &position = player->getPosition(); for (const auto &spectator : Spectators().find<Player>(position, true)) { @@ -3042,28 +3436,26 @@ int PlayerFunctions::luaPlayerSetGhostMode(lua_State* L) { it.second->vip()->notifyStatusChange(player, VipStatus_t::Offline); } } - IOLoginData::updateOnlineStatus(player->getGUID(), false); } else { for (const auto &it : g_game().getPlayers()) { if (!it.second->isAccessPlayer()) { it.second->vip()->notifyStatusChange(player, player->vip()->getStatus()); } } - IOLoginData::updateOnlineStatus(player->getGUID(), true); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetContainerId(lua_State* L) { // player:getContainerId(container) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 2); + const auto &container = Lua::getUserdataShared<Container>(L, 2); if (container) { lua_pushnumber(L, player->getContainerID(container)); } else { @@ -3074,16 +3466,16 @@ int PlayerFunctions::luaPlayerGetContainerId(lua_State* L) { int PlayerFunctions::luaPlayerGetContainerById(lua_State* L) { // player:getContainerById(id) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::shared_ptr<Container> container = player->getContainerByID(getNumber<uint8_t>(L, 2)); + const auto &container = player->getContainerByID(Lua::getNumber<uint8_t>(L, 2)); if (container) { - pushUserdata<Container>(L, container); - setMetatable(L, -1, "Container"); + Lua::pushUserdata<Container>(L, container); + Lua::setMetatable(L, -1, "Container"); } else { lua_pushnil(L); } @@ -3092,9 +3484,9 @@ int PlayerFunctions::luaPlayerGetContainerById(lua_State* L) { int PlayerFunctions::luaPlayerGetContainerIndex(lua_State* L) { // player:getContainerIndex(id) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - lua_pushnumber(L, player->getContainerIndex(getNumber<uint8_t>(L, 2))); + lua_pushnumber(L, player->getContainerIndex(Lua::getNumber<uint8_t>(L, 2))); } else { lua_pushnil(L); } @@ -3103,14 +3495,14 @@ int PlayerFunctions::luaPlayerGetContainerIndex(lua_State* L) { int PlayerFunctions::luaPlayerGetInstantSpells(lua_State* L) { // player:getInstantSpells() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } std::vector<std::shared_ptr<InstantSpell>> spells; - for (auto &[key, spell] : g_spells().getInstantSpells()) { + for (const auto &[key, spell] : g_spells().getInstantSpells()) { if (spell->canCast(player)) { spells.push_back(spell); } @@ -3119,8 +3511,8 @@ int PlayerFunctions::luaPlayerGetInstantSpells(lua_State* L) { lua_createtable(L, spells.size(), 0); int index = 0; - for (auto spell : spells) { - pushInstantSpell(L, *spell); + for (const auto &spell : spells) { + Lua::pushInstantSpell(L, *spell); lua_rawseti(L, -2, ++index); } return 1; @@ -3128,10 +3520,10 @@ int PlayerFunctions::luaPlayerGetInstantSpells(lua_State* L) { int PlayerFunctions::luaPlayerCanCast(lua_State* L) { // player:canCast(spell) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); - const auto spell = getUserdataShared<InstantSpell>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 1); + const auto &spell = Lua::getUserdataShared<InstantSpell>(L, 2); if (player && spell) { - pushBoolean(L, spell->canCast(player)); + Lua::pushBoolean(L, spell->canCast(player)); } else { lua_pushnil(L); } @@ -3140,9 +3532,9 @@ int PlayerFunctions::luaPlayerCanCast(lua_State* L) { int PlayerFunctions::luaPlayerHasChaseMode(lua_State* L) { // player:hasChaseMode() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->chaseMode); + Lua::pushBoolean(L, player->chaseMode); } else { lua_pushnil(L); } @@ -3151,9 +3543,9 @@ int PlayerFunctions::luaPlayerHasChaseMode(lua_State* L) { int PlayerFunctions::luaPlayerHasSecureMode(lua_State* L) { // player:hasSecureMode() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->secureMode); + Lua::pushBoolean(L, player->secureMode); } else { lua_pushnil(L); } @@ -3162,7 +3554,7 @@ int PlayerFunctions::luaPlayerHasSecureMode(lua_State* L) { int PlayerFunctions::luaPlayerGetFightMode(lua_State* L) { // player:getFightMode() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->fightMode); } else { @@ -3173,7 +3565,7 @@ int PlayerFunctions::luaPlayerGetFightMode(lua_State* L) { int PlayerFunctions::luaPlayerGetBaseXpGain(lua_State* L) { // player:getBaseXpGain() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getBaseXpGain()); } else { @@ -3184,11 +3576,11 @@ int PlayerFunctions::luaPlayerGetBaseXpGain(lua_State* L) { int PlayerFunctions::luaPlayerSetBaseXpGain(lua_State* L) { // player:setBaseXpGain(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setBaseXpGain(getNumber<uint16_t>(L, 2)); + player->setBaseXpGain(Lua::getNumber<uint16_t>(L, 2)); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3197,7 +3589,7 @@ int PlayerFunctions::luaPlayerSetBaseXpGain(lua_State* L) { int PlayerFunctions::luaPlayerGetVoucherXpBoost(lua_State* L) { // player:getVoucherXpBoost() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getVoucherXpBoost()); } else { @@ -3208,11 +3600,11 @@ int PlayerFunctions::luaPlayerGetVoucherXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerSetVoucherXpBoost(lua_State* L) { // player:setVoucherXpBoost(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setVoucherXpBoost(getNumber<uint16_t>(L, 2)); + player->setVoucherXpBoost(Lua::getNumber<uint16_t>(L, 2)); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3221,7 +3613,7 @@ int PlayerFunctions::luaPlayerSetVoucherXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerGetGrindingXpBoost(lua_State* L) { // player:getGrindingXpBoost() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getGrindingXpBoost()); } else { @@ -3232,11 +3624,11 @@ int PlayerFunctions::luaPlayerGetGrindingXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerSetGrindingXpBoost(lua_State* L) { // player:setGrindingXpBoost(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setGrindingXpBoost(getNumber<uint16_t>(L, 2)); + player->setGrindingXpBoost(Lua::getNumber<uint16_t>(L, 2)); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3245,7 +3637,7 @@ int PlayerFunctions::luaPlayerSetGrindingXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerGetXpBoostPercent(lua_State* L) { // player:getXpBoostPercent() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getXpBoostPercent()); } else { @@ -3256,11 +3648,11 @@ int PlayerFunctions::luaPlayerGetXpBoostPercent(lua_State* L) { int PlayerFunctions::luaPlayerSetXpBoostPercent(lua_State* L) { // player:setXpBoostPercent(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t percent = getNumber<uint16_t>(L, 2); + const uint16_t percent = Lua::getNumber<uint16_t>(L, 2); player->setXpBoostPercent(percent); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3269,7 +3661,7 @@ int PlayerFunctions::luaPlayerSetXpBoostPercent(lua_State* L) { int PlayerFunctions::luaPlayerGetStaminaXpBoost(lua_State* L) { // player:getStaminaXpBoost() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getStaminaXpBoost()); } else { @@ -3280,11 +3672,11 @@ int PlayerFunctions::luaPlayerGetStaminaXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerSetStaminaXpBoost(lua_State* L) { // player:setStaminaXpBoost(value) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - player->setStaminaXpBoost(getNumber<uint16_t>(L, 2)); + player->setStaminaXpBoost(Lua::getNumber<uint16_t>(L, 2)); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3293,12 +3685,12 @@ int PlayerFunctions::luaPlayerSetStaminaXpBoost(lua_State* L) { int PlayerFunctions::luaPlayerSetXpBoostTime(lua_State* L) { // player:setXpBoostTime(timeLeft) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - uint16_t timeLeft = getNumber<uint16_t>(L, 2); + const uint16_t timeLeft = Lua::getNumber<uint16_t>(L, 2); player->setXpBoostTime(timeLeft); player->sendStats(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3307,7 +3699,7 @@ int PlayerFunctions::luaPlayerSetXpBoostTime(lua_State* L) { int PlayerFunctions::luaPlayerGetXpBoostTime(lua_State* L) { // player:getXpBoostTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getXpBoostTime()); } else { @@ -3318,7 +3710,7 @@ int PlayerFunctions::luaPlayerGetXpBoostTime(lua_State* L) { int PlayerFunctions::luaPlayerGetIdleTime(lua_State* L) { // player:getIdleTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { lua_pushnumber(L, player->getIdleTime()); } else { @@ -3329,7 +3721,7 @@ int PlayerFunctions::luaPlayerGetIdleTime(lua_State* L) { int PlayerFunctions::luaPlayerGetFreeBackpackSlots(lua_State* L) { // player:getFreeBackpackSlots() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); } @@ -3339,11 +3731,11 @@ int PlayerFunctions::luaPlayerGetFreeBackpackSlots(lua_State* L) { } int PlayerFunctions::luaPlayerIsOffline(lua_State* L) { - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player) { - pushBoolean(L, player->isOffline()); + Lua::pushBoolean(L, player->isOffline()); } else { - pushBoolean(L, true); + Lua::pushBoolean(L, true); } return 1; @@ -3351,80 +3743,80 @@ int PlayerFunctions::luaPlayerIsOffline(lua_State* L) { int PlayerFunctions::luaPlayerOpenMarket(lua_State* L) { // player:openMarket() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } player->sendMarketEnter(player->getLastDepotId()); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } // Forge int PlayerFunctions::luaPlayerOpenForge(lua_State* L) { // player:openForge() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } player->sendOpenForge(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerCloseForge(lua_State* L) { // player:closeForge() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } player->closeForgeWindow(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddForgeDusts(lua_State* L) { // player:addForgeDusts(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->addForgeDusts(getNumber<uint64_t>(L, 2, 0)); - pushBoolean(L, true); + player->addForgeDusts(Lua::getNumber<uint64_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveForgeDusts(lua_State* L) { // player:removeForgeDusts(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->removeForgeDusts(getNumber<uint64_t>(L, 2, 0)); - pushBoolean(L, true); + player->removeForgeDusts(Lua::getNumber<uint64_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetForgeDusts(lua_State* L) { // player:getForgeDusts() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -3434,52 +3826,52 @@ int PlayerFunctions::luaPlayerGetForgeDusts(lua_State* L) { int PlayerFunctions::luaPlayerSetForgeDusts(lua_State* L) { // player:setForgeDusts() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->setForgeDusts(getNumber<uint64_t>(L, 2, 0)); - pushBoolean(L, true); + player->setForgeDusts(Lua::getNumber<uint64_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddForgeDustLevel(lua_State* L) { // player:addForgeDustLevel(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->addForgeDustLevel(getNumber<uint64_t>(L, 2, 1)); - pushBoolean(L, true); + player->addForgeDustLevel(Lua::getNumber<uint64_t>(L, 2, 1)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveForgeDustLevel(lua_State* L) { // player:removeForgeDustLevel(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->removeForgeDustLevel(getNumber<uint64_t>(L, 2, 1)); - pushBoolean(L, true); + player->removeForgeDustLevel(Lua::getNumber<uint64_t>(L, 2, 1)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetForgeDustLevel(lua_State* L) { // player:getForgeDustLevel() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -3489,10 +3881,10 @@ int PlayerFunctions::luaPlayerGetForgeDustLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetForgeSlivers(lua_State* L) { // player:getForgeSlivers() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -3503,10 +3895,10 @@ int PlayerFunctions::luaPlayerGetForgeSlivers(lua_State* L) { int PlayerFunctions::luaPlayerGetForgeCores(lua_State* L) { // player:getForgeCores() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -3517,25 +3909,25 @@ int PlayerFunctions::luaPlayerGetForgeCores(lua_State* L) { int PlayerFunctions::luaPlayerSetFaction(lua_State* L) { // player:setFaction(factionId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player == nullptr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - Faction_t factionId = getNumber<Faction_t>(L, 2); + const Faction_t factionId = Lua::getNumber<Faction_t>(L, 2); player->setFaction(factionId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetFaction(lua_State* L) { // player:getFaction() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (player == nullptr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -3545,59 +3937,59 @@ int PlayerFunctions::luaPlayerGetFaction(lua_State* L) { int PlayerFunctions::luaPlayerIsUIExhausted(lua_State* L) { // player:isUIExhausted() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - uint16_t time = getNumber<uint16_t>(L, 2); - pushBoolean(L, player->isUIExhausted(time)); + const uint16_t time = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, player->isUIExhausted(time)); return 1; } int PlayerFunctions::luaPlayerUpdateUIExhausted(lua_State* L) { // player:updateUIExhausted(exhaustionTime = 250) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } player->updateUIExhausted(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } // Bosstiary Cooldown Timer int PlayerFunctions::luaPlayerBosstiaryCooldownTimer(lua_State* L) { // player:sendBosstiaryCooldownTimer() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } player->sendBosstiaryCooldownTimer(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetBosstiaryLevel(lua_State* L) { // player:getBosstiaryLevel(name) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1); player) { - const auto mtype = g_monsters().getMonsterType(getString(L, 2)); + const auto &mtype = g_monsters().getMonsterType(Lua::getString(L, 2)); if (mtype) { - uint32_t bossId = mtype->info.raceid; + const uint32_t bossId = mtype->info.raceid; if (bossId == 0) { lua_pushnil(L); return 0; } - auto level = g_ioBosstiary().getBossCurrentLevel(player, bossId); + const auto level = g_ioBosstiary().getBossCurrentLevel(player, bossId); lua_pushnumber(L, level); } else { lua_pushnil(L); @@ -3610,16 +4002,16 @@ int PlayerFunctions::luaPlayerGetBosstiaryLevel(lua_State* L) { int PlayerFunctions::luaPlayerGetBosstiaryKills(lua_State* L) { // player:getBosstiaryKills(name) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1); player) { - const auto mtype = g_monsters().getMonsterType(getString(L, 2)); + const auto &mtype = g_monsters().getMonsterType(Lua::getString(L, 2)); if (mtype) { - uint32_t bossId = mtype->info.raceid; + const uint32_t bossId = mtype->info.raceid; if (bossId == 0) { lua_pushnil(L); return 0; } - uint32_t currentKills = player->getBestiaryKillCount(static_cast<uint16_t>(bossId)); + const uint32_t currentKills = player->getBestiaryKillCount(static_cast<uint16_t>(bossId)); lua_pushnumber(L, currentKills); } else { lua_pushnil(L); @@ -3632,12 +4024,12 @@ int PlayerFunctions::luaPlayerGetBosstiaryKills(lua_State* L) { int PlayerFunctions::luaPlayerAddBosstiaryKill(lua_State* L) { // player:addBosstiaryKill(name[, amount = 1]) - if (std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + if (const auto &player = Lua::getUserdataShared<Player>(L, 1); player) { - const auto mtype = g_monsters().getMonsterType(getString(L, 2)); + const auto &mtype = g_monsters().getMonsterType(Lua::getString(L, 2)); if (mtype) { - g_ioBosstiary().addBosstiaryKill(player, mtype, getNumber<uint32_t>(L, 3, 1)); - pushBoolean(L, true); + g_ioBosstiary().addBosstiaryKill(player, mtype, Lua::getNumber<uint32_t>(L, 3, 1)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -3649,64 +4041,64 @@ int PlayerFunctions::luaPlayerAddBosstiaryKill(lua_State* L) { int PlayerFunctions::luaPlayerSetBossPoints(lua_State* L) { // player:setBossPoints() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->setBossPoints(getNumber<uint32_t>(L, 2, 0)); - pushBoolean(L, true); + player->setBossPoints(Lua::getNumber<uint32_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSetRemoveBossTime(lua_State* L) { // player:setRemoveBossTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->setRemoveBossTime(getNumber<uint8_t>(L, 2, 0)); - pushBoolean(L, true); + player->setRemoveBossTime(Lua::getNumber<uint8_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetSlotBossId(lua_State* L) { // player:getSlotBossId(slotId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - uint8_t slotId = getNumber<uint8_t>(L, 2); - auto bossId = player->getSlotBossId(slotId); + const uint8_t slotId = Lua::getNumber<uint8_t>(L, 2); + const auto bossId = player->getSlotBossId(slotId); lua_pushnumber(L, static_cast<lua_Number>(bossId)); return 1; } int PlayerFunctions::luaPlayerGetBossBonus(lua_State* L) { // player:getBossBonus(slotId) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - uint8_t slotId = getNumber<uint8_t>(L, 2); - auto bossId = player->getSlotBossId(slotId); + const uint8_t slotId = Lua::getNumber<uint8_t>(L, 2); + const auto bossId = player->getSlotBossId(slotId); - uint32_t playerBossPoints = player->getBossPoints(); - uint16_t currentBonus = g_ioBosstiary().calculateLootBonus(playerBossPoints); + const uint32_t playerBossPoints = player->getBossPoints(); + const uint16_t currentBonus = g_ioBosstiary().calculateLootBonus(playerBossPoints); - auto bossLevel = g_ioBosstiary().getBossCurrentLevel(player, bossId); - uint16_t bonusBoss = currentBonus + (bossLevel == 3 ? 25 : 0); + const auto bossLevel = g_ioBosstiary().getBossCurrentLevel(player, bossId); + const uint16_t bonusBoss = currentBonus + (bossLevel == 3 ? 25 : 0); lua_pushnumber(L, static_cast<lua_Number>(bonusBoss)); return 1; @@ -3714,65 +4106,65 @@ int PlayerFunctions::luaPlayerGetBossBonus(lua_State* L) { int PlayerFunctions::luaPlayerSendSingleSoundEffect(lua_State* L) { // player:sendSingleSoundEffect(soundId[, actor = true]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - SoundEffect_t soundEffect = getNumber<SoundEffect_t>(L, 2); - bool actor = getBoolean(L, 3, true); + const SoundEffect_t soundEffect = Lua::getNumber<SoundEffect_t>(L, 2); + const bool actor = Lua::getBoolean(L, 3, true); player->sendSingleSoundEffect(player->getPosition(), soundEffect, actor ? SourceEffect_t::OWN : SourceEffect_t::GLOBAL); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendDoubleSoundEffect(lua_State* L) { // player:sendDoubleSoundEffect(mainSoundId, secondarySoundId[, actor = true]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - SoundEffect_t mainSoundEffect = getNumber<SoundEffect_t>(L, 2); - SoundEffect_t secondarySoundEffect = getNumber<SoundEffect_t>(L, 3); - bool actor = getBoolean(L, 4, true); + const SoundEffect_t mainSoundEffect = Lua::getNumber<SoundEffect_t>(L, 2); + const SoundEffect_t secondarySoundEffect = Lua::getNumber<SoundEffect_t>(L, 3); + const bool actor = Lua::getBoolean(L, 4, true); player->sendDoubleSoundEffect(player->getPosition(), mainSoundEffect, actor ? SourceEffect_t::OWN : SourceEffect_t::GLOBAL, secondarySoundEffect, actor ? SourceEffect_t::OWN : SourceEffect_t::GLOBAL); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetName(lua_State* L) { // player:getName() - const auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushString(L, player->getName()); + Lua::pushString(L, player->getName()); return 1; } int PlayerFunctions::luaPlayerChangeName(lua_State* L) { // player:changeName(newName) - const auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } if (player->isOnline()) { player->removePlayer(true, true); } player->kv()->remove("namelock"); - auto newName = getString(L, 2); + const auto newName = Lua::getString(L, 2); player->setName(newName); g_saveManager().savePlayer(player); return 1; @@ -3780,64 +4172,64 @@ int PlayerFunctions::luaPlayerChangeName(lua_State* L) { int PlayerFunctions::luaPlayerHasGroupFlag(lua_State* L) { // player:hasGroupFlag(flag) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushBoolean(L, player->hasFlag(getNumber<PlayerFlags_t>(L, 2))); + Lua::pushBoolean(L, player->hasFlag(Lua::getNumber<PlayerFlags_t>(L, 2))); return 1; } int PlayerFunctions::luaPlayerSetGroupFlag(lua_State* L) { // player:setGroupFlag(flag) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->setFlag(getNumber<PlayerFlags_t>(L, 2)); + player->setFlag(Lua::getNumber<PlayerFlags_t>(L, 2)); return 1; } int PlayerFunctions::luaPlayerRemoveGroupFlag(lua_State* L) { // player:removeGroupFlag(flag) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - player->removeFlag(getNumber<PlayerFlags_t>(L, 2)); + player->removeFlag(Lua::getNumber<PlayerFlags_t>(L, 2)); return 1; } // Hazard system int PlayerFunctions::luaPlayerAddHazardSystemPoints(lua_State* L) { // player:setHazardSystemPoints(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - player->setHazardSystemPoints(getNumber<int32_t>(L, 2, 0)); - pushBoolean(L, true); + player->setHazardSystemPoints(Lua::getNumber<int32_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetHazardSystemPoints(lua_State* L) { // player:getHazardSystemPoints() - const auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - pushBoolean(L, false); - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } @@ -3847,20 +4239,20 @@ int PlayerFunctions::luaPlayerGetHazardSystemPoints(lua_State* L) { int PlayerFunctions::luaPlayerSetLoyaltyBonus(lua_State* L) { // player:setLoyaltyBonus(amount) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - player->setLoyaltyBonus(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + player->setLoyaltyBonus(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetLoyaltyBonus(lua_State* L) { // player:getLoyaltyBonus() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -3872,7 +4264,7 @@ int PlayerFunctions::luaPlayerGetLoyaltyBonus(lua_State* L) { int PlayerFunctions::luaPlayerGetLoyaltyPoints(lua_State* L) { // player:getLoyaltyPoints() - const auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -3884,51 +4276,51 @@ int PlayerFunctions::luaPlayerGetLoyaltyPoints(lua_State* L) { int PlayerFunctions::luaPlayerGetLoyaltyTitle(lua_State* L) { // player:getLoyaltyTitle() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - pushString(L, player->getLoyaltyTitle()); + Lua::pushString(L, player->getLoyaltyTitle()); return 1; } int PlayerFunctions::luaPlayerSetLoyaltyTitle(lua_State* L) { // player:setLoyaltyTitle(name) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - player->setLoyaltyTitle(getString(L, 2)); - pushBoolean(L, true); + player->setLoyaltyTitle(Lua::getString(L, 2)); + Lua::pushBoolean(L, true); return 1; } // Wheel of destiny system int PlayerFunctions::luaPlayerInstantSkillWOD(lua_State* L) { // player:instantSkillWOD(name[, value]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - std::string name = getString(L, 2); + const std::string name = Lua::getString(L, 2); if (lua_gettop(L) == 2) { - pushBoolean(L, player->wheel()->getInstant(name)); + Lua::pushBoolean(L, player->wheel()->getInstant(name)); } else { - player->wheel()->setSpellInstant(name, getBoolean(L, 3)); - pushBoolean(L, true); + player->wheel()->setSpellInstant(name, Lua::getBoolean(L, 3)); + Lua::pushBoolean(L, true); } return 1; } int PlayerFunctions::luaPlayerUpgradeSpellWOD(lua_State* L) { // player:upgradeSpellsWOD([name[, add]]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -3939,26 +4331,26 @@ int PlayerFunctions::luaPlayerUpgradeSpellWOD(lua_State* L) { return 1; } - std::string name = getString(L, 2); + const std::string name = Lua::getString(L, 2); if (lua_gettop(L) == 2) { lua_pushnumber(L, static_cast<lua_Number>(player->wheel()->getSpellUpgrade(name))); return 1; } - bool add = getBoolean(L, 3); + const bool add = Lua::getBoolean(L, 3); if (add) { player->wheel()->upgradeSpell(name); } else { player->wheel()->downgradeSpell(name); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRevelationStageWOD(lua_State* L) { // player:revelationStageWOD([name[, set]]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -3969,22 +4361,22 @@ int PlayerFunctions::luaPlayerRevelationStageWOD(lua_State* L) { return 1; } - std::string name = getString(L, 2); + const std::string name = Lua::getString(L, 2); if (lua_gettop(L) == 2) { lua_pushnumber(L, static_cast<lua_Number>(player->wheel()->getStage(name))); return 1; } - bool value = getNumber<uint8_t>(L, 3); + const bool value = Lua::getNumber<uint8_t>(L, 3); player->wheel()->setSpellInstant(name, value); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerReloadData(lua_State* L) { // player:reloadData() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; @@ -3995,87 +4387,87 @@ int PlayerFunctions::luaPlayerReloadData(lua_State* L) { player->sendBasicData(); player->wheel()->sendGiftOfLifeCooldown(); g_game().reloadCreature(player); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerOnThinkWheelOfDestiny(lua_State* L) { // player:onThinkWheelOfDestiny([force = false]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - player->wheel()->onThink(getBoolean(L, 2, false)); - pushBoolean(L, true); + player->wheel()->onThink(Lua::getBoolean(L, 2, false)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAvatarTimer(lua_State* L) { // player:avatarTimer([value]) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } if (lua_gettop(L) == 1) { - lua_pushnumber(L, (lua_Number)player->wheel()->getOnThinkTimer(WheelOnThink_t::AVATAR_SPELL)); + lua_pushnumber(L, static_cast<lua_Number>(player->wheel()->getOnThinkTimer(WheelOnThink_t::AVATAR_SPELL))); } else { - player->wheel()->setOnThinkTimer(WheelOnThink_t::AVATAR_SPELL, getNumber<int64_t>(L, 2)); - pushBoolean(L, true); + player->wheel()->setOnThinkTimer(WheelOnThink_t::AVATAR_SPELL, Lua::getNumber<int64_t>(L, 2)); + Lua::pushBoolean(L, true); } return 1; } int PlayerFunctions::luaPlayerGetWheelSpellAdditionalArea(lua_State* L) { // player:getWheelSpellAdditionalArea(spellname) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - auto spellName = getString(L, 2); + const auto spellName = Lua::getString(L, 2); if (spellName.empty()) { - reportErrorFunc("Spell name is empty"); - pushBoolean(L, false); + Lua::reportErrorFunc("Spell name is empty"); + Lua::pushBoolean(L, false); return 0; } - auto spell = g_spells().getInstantSpellByName(spellName); + const auto &spell = g_spells().getInstantSpellByName(spellName); if (!spell) { - reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - pushBoolean(L, player->wheel()->getSpellAdditionalArea(spellName)); + Lua::pushBoolean(L, player->wheel()->getSpellAdditionalArea(spellName)); return 1; } int PlayerFunctions::luaPlayerGetWheelSpellAdditionalTarget(lua_State* L) { // player:getWheelSpellAdditionalTarget(spellname) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - auto spellName = getString(L, 2); + const auto spellName = Lua::getString(L, 2); if (spellName.empty()) { - reportErrorFunc("Spell name is empty"); - pushBoolean(L, false); + Lua::reportErrorFunc("Spell name is empty"); + Lua::pushBoolean(L, false); return 0; } - auto spell = g_spells().getInstantSpellByName(spellName); + const auto &spell = g_spells().getInstantSpellByName(spellName); if (!spell) { - reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -4085,24 +4477,24 @@ int PlayerFunctions::luaPlayerGetWheelSpellAdditionalTarget(lua_State* L) { int PlayerFunctions::luaPlayerGetWheelSpellAdditionalDuration(lua_State* L) { // player:getWheelSpellAdditionalDuration(spellname) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } - auto spellName = getString(L, 2); + const auto spellName = Lua::getString(L, 2); if (spellName.empty()) { - reportErrorFunc("Spell name is empty"); - pushBoolean(L, false); + Lua::reportErrorFunc("Spell name is empty"); + Lua::pushBoolean(L, false); return 0; } - auto spell = g_spells().getInstantSpellByName(spellName); + const auto &spell = g_spells().getInstantSpellByName(spellName); if (!spell) { - reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); + Lua::pushBoolean(L, false); return 0; } @@ -4112,46 +4504,46 @@ int PlayerFunctions::luaPlayerGetWheelSpellAdditionalDuration(lua_State* L) { int PlayerFunctions::luaPlayerUpdateConcoction(lua_State* L) { // player:updateConcoction(itemid, timeLeft) - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - player->updateConcoction(getNumber<uint16_t>(L, 2), getNumber<uint16_t>(L, 3)); - pushBoolean(L, true); + player->updateConcoction(Lua::getNumber<uint16_t>(L, 2), Lua::getNumber<uint16_t>(L, 3)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerClearSpellCooldowns(lua_State* L) { // player:clearSpellCooldowns() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } player->clearCooldowns(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerIsVip(lua_State* L) { // player:isVip() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, player->isVip()); + Lua::pushBoolean(L, player->isVip()); return 1; } int PlayerFunctions::luaPlayerGetVipDays(lua_State* L) { // player:getVipDays() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -4161,10 +4553,10 @@ int PlayerFunctions::luaPlayerGetVipDays(lua_State* L) { int PlayerFunctions::luaPlayerGetVipTime(lua_State* L) { // player:getVipTime() - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -4174,102 +4566,102 @@ int PlayerFunctions::luaPlayerGetVipTime(lua_State* L) { int PlayerFunctions::luaPlayerKV(lua_State* L) { // player:kv() - auto player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushUserdata<KV>(L, player->kv()); - setMetatable(L, -1, "KV"); + Lua::pushUserdata<KV>(L, player->kv()); + Lua::setMetatable(L, -1, "KV"); return 1; } int PlayerFunctions::luaPlayerGetStoreInbox(lua_State* L) { // player:getStoreInbox() - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - if (auto item = player->getStoreInbox()) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + if (const auto &item = player->getStoreInbox()) { + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PlayerFunctions::luaPlayerHasAchievement(lua_State* L) { // player:hasAchievement(id or name) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } uint16_t achievementId = 0; - if (isNumber(L, 2)) { - achievementId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + achievementId = Lua::getNumber<uint16_t>(L, 2); } else { - achievementId = g_game().getAchievementByName(getString(L, 2)).id; + achievementId = g_game().getAchievementByName(Lua::getString(L, 2)).id; } - pushBoolean(L, player->achiev()->isUnlocked(achievementId)); + Lua::pushBoolean(L, player->achiev()->isUnlocked(achievementId)); return 1; } int PlayerFunctions::luaPlayerAddAchievement(lua_State* L) { // player:addAchievement(id or name[, sendMessage = true]) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } uint16_t achievementId = 0; - if (isNumber(L, 2)) { - achievementId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + achievementId = Lua::getNumber<uint16_t>(L, 2); } else { - achievementId = g_game().getAchievementByName(getString(L, 2)).id; + achievementId = g_game().getAchievementByName(Lua::getString(L, 2)).id; } - bool success = player->achiev()->add(achievementId, getBoolean(L, 3, true)); + const bool success = player->achiev()->add(achievementId, Lua::getBoolean(L, 3, true)); if (success) { player->sendTakeScreenshot(SCREENSHOT_TYPE_ACHIEVEMENT); } - pushBoolean(L, success); + Lua::pushBoolean(L, success); return 1; } int PlayerFunctions::luaPlayerRemoveAchievement(lua_State* L) { // player:removeAchievement(id or name) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } uint16_t achievementId = 0; - if (isNumber(L, 2)) { - achievementId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + achievementId = Lua::getNumber<uint16_t>(L, 2); } else { - achievementId = g_game().getAchievementByName(getString(L, 2)).id; + achievementId = g_game().getAchievementByName(Lua::getString(L, 2)).id; } - pushBoolean(L, player->achiev()->remove(achievementId)); + Lua::pushBoolean(L, player->achiev()->remove(achievementId)); return 1; } int PlayerFunctions::luaPlayerGetAchievementPoints(lua_State* L) { // player:getAchievementPoints() - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } @@ -4279,79 +4671,79 @@ int PlayerFunctions::luaPlayerGetAchievementPoints(lua_State* L) { int PlayerFunctions::luaPlayerAddAchievementPoints(lua_State* L) { // player:addAchievementPoints(amount) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - auto points = getNumber<uint16_t>(L, 2); + const auto points = Lua::getNumber<uint16_t>(L, 2); if (points > 0) { player->achiev()->addPoints(points); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveAchievementPoints(lua_State* L) { // player:removeAchievementPoints(amount) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - auto points = getNumber<uint16_t>(L, 2); + const auto points = Lua::getNumber<uint16_t>(L, 2); if (points > 0) { player->achiev()->removePoints(points); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddBadge(lua_State* L) { // player:addBadge(id) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - player->badge()->add(getNumber<uint8_t>(L, 2, 0)); - pushBoolean(L, true); + player->badge()->add(Lua::getNumber<uint8_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerAddTitle(lua_State* L) { // player:addTitle(id) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - player->title()->manage(true, getNumber<uint8_t>(L, 2, 0)); - pushBoolean(L, true); + player->title()->manage(true, Lua::getNumber<uint8_t>(L, 2, 0)); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerGetTitles(lua_State* L) { // player:getTitles() - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - auto playerTitles = player->title()->getUnlockedTitles(); + const auto playerTitles = player->title()->getUnlockedTitles(); lua_createtable(L, static_cast<int>(playerTitles.size()), 0); int index = 0; for (const auto &title : playerTitles) { lua_createtable(L, 0, 3); - setField(L, "id", title.first.m_id); - setField(L, "name", player->title()->getNameBySex(player->getSex(), title.first.m_maleName, title.first.m_femaleName)); - setField(L, "description", title.first.m_description); + Lua::setField(L, "id", title.first.m_id); + Lua::setField(L, "name", player->title()->getNameBySex(player->getSex(), title.first.m_maleName, title.first.m_femaleName)); + Lua::setField(L, "description", title.first.m_description); lua_rawseti(L, -2, ++index); } return 1; @@ -4359,101 +4751,101 @@ int PlayerFunctions::luaPlayerGetTitles(lua_State* L) { int PlayerFunctions::luaPlayerSetCurrentTitle(lua_State* L) { // player:setCurrentTitle(id) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - const auto &title = g_game().getTitleById(getNumber<uint8_t>(L, 2, 0)); + const auto &title = g_game().getTitleById(Lua::getNumber<uint8_t>(L, 2, 0)); if (title.m_id == 0) { - reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); return 1; } player->title()->setCurrentTitle(title.m_id); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerCreateTransactionSummary(lua_State* L) { // player:createTransactionSummary(type, amount[, id = 0]) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - auto type = getNumber<uint8_t>(L, 2, 0); + const auto type = Lua::getNumber<uint8_t>(L, 2, 0); if (type == 0) { - reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); return 1; } - auto amount = getNumber<uint16_t>(L, 3, 1); - auto id = getString(L, 4, ""); + const auto amount = Lua::getNumber<uint16_t>(L, 3, 1); + const auto id = Lua::getString(L, 4, ""); player->cyclopedia()->updateStoreSummary(type, amount, id); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerTakeScreenshot(lua_State* L) { // player:takeScreenshot(screenshotType) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - auto screenshotType = getNumber<Screenshot_t>(L, 2); + const auto screenshotType = Lua::getNumber<Screenshot_t>(L, 2); player->sendTakeScreenshot(screenshotType); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendIconBakragore(lua_State* L) { // player:sendIconBakragore() - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - auto iconType = getNumber<IconBakragore>(L, 2); + const auto iconType = Lua::getNumber<IconBakragore>(L, 2); player->sendIconBakragore(iconType); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerRemoveIconBakragore(lua_State* L) { // player:removeIconBakragore(iconType or nil for remove all bakragore icons) - const auto &player = getUserdataShared<Player>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 1); if (!player) { lua_pushnil(L); return 1; } - auto iconType = getNumber<IconBakragore>(L, 2, IconBakragore::None); + const auto iconType = Lua::getNumber<IconBakragore>(L, 2, IconBakragore::None); if (iconType == IconBakragore::None) { player->removeBakragoreIcons(); } else { player->removeBakragoreIcon(iconType); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PlayerFunctions::luaPlayerSendCreatureAppear(lua_State* L) { - auto player = getUserdataShared<Player>(L, 1); + auto player = Lua::getUserdataShared<Player>(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - bool isLogin = getBoolean(L, 2, false); + bool isLogin = Lua::getBoolean(L, 2, false); player->sendCreatureAppear(player, player->getPosition(), isLogin); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/creatures/player/player_functions.hpp b/src/lua/functions/creatures/player/player_functions.hpp index aa4db5857f7..ab617c35132 100644 --- a/src/lua/functions/creatures/player/player_functions.hpp +++ b/src/lua/functions/creatures/player/player_functions.hpp @@ -9,383 +9,17 @@ #pragma once -#include "lua/scripts/luascript.hpp" #include "lua/functions/creatures/player/group_functions.hpp" #include "lua/functions/creatures/player/guild_functions.hpp" #include "lua/functions/creatures/player/mount_functions.hpp" #include "lua/functions/creatures/player/party_functions.hpp" #include "lua/functions/creatures/player/vocation_functions.hpp" -class PlayerFunctions final : LuaScriptInterface { -private: - static void init(lua_State* L) { - registerSharedClass(L, "Player", "Creature", PlayerFunctions::luaPlayerCreate); - registerMetaMethod(L, "Player", "__eq", PlayerFunctions::luaUserdataCompare); - - registerMethod(L, "Player", "resetCharmsBestiary", PlayerFunctions::luaPlayerResetCharmsMonsters); - registerMethod(L, "Player", "unlockAllCharmRunes", PlayerFunctions::luaPlayerUnlockAllCharmRunes); - registerMethod(L, "Player", "addCharmPoints", PlayerFunctions::luaPlayeraddCharmPoints); - registerMethod(L, "Player", "isPlayer", PlayerFunctions::luaPlayerIsPlayer); - - registerMethod(L, "Player", "getGuid", PlayerFunctions::luaPlayerGetGuid); - registerMethod(L, "Player", "getIp", PlayerFunctions::luaPlayerGetIp); - registerMethod(L, "Player", "getAccountId", PlayerFunctions::luaPlayerGetAccountId); - registerMethod(L, "Player", "getLastLoginSaved", PlayerFunctions::luaPlayerGetLastLoginSaved); - registerMethod(L, "Player", "getLastLogout", PlayerFunctions::luaPlayerGetLastLogout); - - registerMethod(L, "Player", "getAccountType", PlayerFunctions::luaPlayerGetAccountType); - registerMethod(L, "Player", "setAccountType", PlayerFunctions::luaPlayerSetAccountType); - - registerMethod(L, "Player", "isMonsterBestiaryUnlocked", PlayerFunctions::luaPlayerIsMonsterBestiaryUnlocked); - registerMethod(L, "Player", "addBestiaryKill", PlayerFunctions::luaPlayerAddBestiaryKill); - registerMethod(L, "Player", "charmExpansion", PlayerFunctions::luaPlayercharmExpansion); - registerMethod(L, "Player", "getCharmMonsterType", PlayerFunctions::luaPlayergetCharmMonsterType); - - registerMethod(L, "Player", "isMonsterPrey", PlayerFunctions::luaPlayerisMonsterPrey); - registerMethod(L, "Player", "getPreyCards", PlayerFunctions::luaPlayerGetPreyCards); - registerMethod(L, "Player", "getPreyLootPercentage", PlayerFunctions::luaPlayerGetPreyLootPercentage); - registerMethod(L, "Player", "getPreyExperiencePercentage", PlayerFunctions::luaPlayerGetPreyExperiencePercentage); - registerMethod(L, "Player", "preyThirdSlot", PlayerFunctions::luaPlayerPreyThirdSlot); - registerMethod(L, "Player", "taskHuntingThirdSlot", PlayerFunctions::luaPlayerTaskThirdSlot); - registerMethod(L, "Player", "removePreyStamina", PlayerFunctions::luaPlayerRemovePreyStamina); - registerMethod(L, "Player", "addPreyCards", PlayerFunctions::luaPlayerAddPreyCards); - registerMethod(L, "Player", "removeTaskHuntingPoints", PlayerFunctions::luaPlayerRemoveTaskHuntingPoints); - registerMethod(L, "Player", "getTaskHuntingPoints", PlayerFunctions::luaPlayerGetTaskHuntingPoints); - registerMethod(L, "Player", "addTaskHuntingPoints", PlayerFunctions::luaPlayerAddTaskHuntingPoints); +enum class PlayerIcon : uint8_t; +enum class IconBakragore : uint8_t; - registerMethod(L, "Player", "getCapacity", PlayerFunctions::luaPlayerGetCapacity); - registerMethod(L, "Player", "setCapacity", PlayerFunctions::luaPlayerSetCapacity); - - registerMethod(L, "Player", "isTraining", PlayerFunctions::luaPlayerGetIsTraining); - registerMethod(L, "Player", "setTraining", PlayerFunctions::luaPlayerSetTraining); - - registerMethod(L, "Player", "getFreeCapacity", PlayerFunctions::luaPlayerGetFreeCapacity); - - registerMethod(L, "Player", "getKills", PlayerFunctions::luaPlayerGetKills); - registerMethod(L, "Player", "setKills", PlayerFunctions::luaPlayerSetKills); - - registerMethod(L, "Player", "getReward", PlayerFunctions::luaPlayerGetReward); - registerMethod(L, "Player", "removeReward", PlayerFunctions::luaPlayerRemoveReward); - registerMethod(L, "Player", "getRewardList", PlayerFunctions::luaPlayerGetRewardList); - - registerMethod(L, "Player", "setDailyReward", PlayerFunctions::luaPlayerSetDailyReward); - - registerMethod(L, "Player", "sendInventory", PlayerFunctions::luaPlayerSendInventory); - registerMethod(L, "Player", "sendLootStats", PlayerFunctions::luaPlayerSendLootStats); - registerMethod(L, "Player", "updateSupplyTracker", PlayerFunctions::luaPlayerUpdateSupplyTracker); - registerMethod(L, "Player", "updateKillTracker", PlayerFunctions::luaPlayerUpdateKillTracker); - - registerMethod(L, "Player", "getDepotLocker", PlayerFunctions::luaPlayerGetDepotLocker); - registerMethod(L, "Player", "getDepotChest", PlayerFunctions::luaPlayerGetDepotChest); - registerMethod(L, "Player", "getInbox", PlayerFunctions::luaPlayerGetInbox); - - registerMethod(L, "Player", "getSkullTime", PlayerFunctions::luaPlayerGetSkullTime); - registerMethod(L, "Player", "setSkullTime", PlayerFunctions::luaPlayerSetSkullTime); - registerMethod(L, "Player", "getDeathPenalty", PlayerFunctions::luaPlayerGetDeathPenalty); - - registerMethod(L, "Player", "getExperience", PlayerFunctions::luaPlayerGetExperience); - registerMethod(L, "Player", "addExperience", PlayerFunctions::luaPlayerAddExperience); - registerMethod(L, "Player", "removeExperience", PlayerFunctions::luaPlayerRemoveExperience); - registerMethod(L, "Player", "getLevel", PlayerFunctions::luaPlayerGetLevel); - - registerMethod(L, "Player", "getMagicShieldCapacityFlat", PlayerFunctions::luaPlayerGetMagicShieldCapacityFlat); - registerMethod(L, "Player", "getMagicShieldCapacityPercent", PlayerFunctions::luaPlayerGetMagicShieldCapacityPercent); - - registerMethod(L, "Player", "sendSpellCooldown", PlayerFunctions::luaPlayerSendSpellCooldown); - registerMethod(L, "Player", "sendSpellGroupCooldown", PlayerFunctions::luaPlayerSendSpellGroupCooldown); - - registerMethod(L, "Player", "getMagicLevel", PlayerFunctions::luaPlayerGetMagicLevel); - registerMethod(L, "Player", "getBaseMagicLevel", PlayerFunctions::luaPlayerGetBaseMagicLevel); - registerMethod(L, "Player", "getMana", PlayerFunctions::luaPlayerGetMana); - registerMethod(L, "Player", "addMana", PlayerFunctions::luaPlayerAddMana); - registerMethod(L, "Player", "getMaxMana", PlayerFunctions::luaPlayerGetMaxMana); - registerMethod(L, "Player", "setMaxMana", PlayerFunctions::luaPlayerSetMaxMana); - registerMethod(L, "Player", "getManaSpent", PlayerFunctions::luaPlayerGetManaSpent); - registerMethod(L, "Player", "addManaSpent", PlayerFunctions::luaPlayerAddManaSpent); - - registerMethod(L, "Player", "getBaseMaxHealth", PlayerFunctions::luaPlayerGetBaseMaxHealth); - registerMethod(L, "Player", "getBaseMaxMana", PlayerFunctions::luaPlayerGetBaseMaxMana); - - registerMethod(L, "Player", "getSkillLevel", PlayerFunctions::luaPlayerGetSkillLevel); - registerMethod(L, "Player", "getEffectiveSkillLevel", PlayerFunctions::luaPlayerGetEffectiveSkillLevel); - registerMethod(L, "Player", "getSkillPercent", PlayerFunctions::luaPlayerGetSkillPercent); - registerMethod(L, "Player", "getSkillTries", PlayerFunctions::luaPlayerGetSkillTries); - registerMethod(L, "Player", "addSkillTries", PlayerFunctions::luaPlayerAddSkillTries); - - registerMethod(L, "Player", "setLevel", PlayerFunctions::luaPlayerSetLevel); - registerMethod(L, "Player", "setMagicLevel", PlayerFunctions::luaPlayerSetMagicLevel); - registerMethod(L, "Player", "setSkillLevel", PlayerFunctions::luaPlayerSetSkillLevel); - - registerMethod(L, "Player", "addOfflineTrainingTime", PlayerFunctions::luaPlayerAddOfflineTrainingTime); - registerMethod(L, "Player", "getOfflineTrainingTime", PlayerFunctions::luaPlayerGetOfflineTrainingTime); - registerMethod(L, "Player", "removeOfflineTrainingTime", PlayerFunctions::luaPlayerRemoveOfflineTrainingTime); - - registerMethod(L, "Player", "addOfflineTrainingTries", PlayerFunctions::luaPlayerAddOfflineTrainingTries); - - registerMethod(L, "Player", "getOfflineTrainingSkill", PlayerFunctions::luaPlayerGetOfflineTrainingSkill); - registerMethod(L, "Player", "setOfflineTrainingSkill", PlayerFunctions::luaPlayerSetOfflineTrainingSkill); - - registerMethod(L, "Player", "getItemCount", PlayerFunctions::luaPlayerGetItemCount); - registerMethod(L, "Player", "getStashItemCount", PlayerFunctions::luaPlayerGetStashItemCount); - registerMethod(L, "Player", "getItemById", PlayerFunctions::luaPlayerGetItemById); - - registerMethod(L, "Player", "getVocation", PlayerFunctions::luaPlayerGetVocation); - registerMethod(L, "Player", "setVocation", PlayerFunctions::luaPlayerSetVocation); - registerMethod(L, "Player", "isPromoted", PlayerFunctions::luaPlayerIsPromoted); - - registerMethod(L, "Player", "getSex", PlayerFunctions::luaPlayerGetSex); - registerMethod(L, "Player", "setSex", PlayerFunctions::luaPlayerSetSex); - - registerMethod(L, "Player", "getPronoun", PlayerFunctions::luaPlayerGetPronoun); - registerMethod(L, "Player", "setPronoun", PlayerFunctions::luaPlayerSetPronoun); - - registerMethod(L, "Player", "getTown", PlayerFunctions::luaPlayerGetTown); - registerMethod(L, "Player", "setTown", PlayerFunctions::luaPlayerSetTown); - - registerMethod(L, "Player", "getGuild", PlayerFunctions::luaPlayerGetGuild); - registerMethod(L, "Player", "setGuild", PlayerFunctions::luaPlayerSetGuild); - - registerMethod(L, "Player", "getGuildLevel", PlayerFunctions::luaPlayerGetGuildLevel); - registerMethod(L, "Player", "setGuildLevel", PlayerFunctions::luaPlayerSetGuildLevel); - - registerMethod(L, "Player", "getGuildNick", PlayerFunctions::luaPlayerGetGuildNick); - registerMethod(L, "Player", "setGuildNick", PlayerFunctions::luaPlayerSetGuildNick); - - registerMethod(L, "Player", "getGroup", PlayerFunctions::luaPlayerGetGroup); - registerMethod(L, "Player", "setGroup", PlayerFunctions::luaPlayerSetGroup); - - registerMethod(L, "Player", "setSpecialContainersAvailable", PlayerFunctions::luaPlayerSetSpecialContainersAvailable); - registerMethod(L, "Player", "getStashCount", PlayerFunctions::luaPlayerGetStashCounter); - registerMethod(L, "Player", "openStash", PlayerFunctions::luaPlayerOpenStash); - - registerMethod(L, "Player", "getStamina", PlayerFunctions::luaPlayerGetStamina); - registerMethod(L, "Player", "setStamina", PlayerFunctions::luaPlayerSetStamina); - - registerMethod(L, "Player", "getSoul", PlayerFunctions::luaPlayerGetSoul); - registerMethod(L, "Player", "addSoul", PlayerFunctions::luaPlayerAddSoul); - registerMethod(L, "Player", "getMaxSoul", PlayerFunctions::luaPlayerGetMaxSoul); - - registerMethod(L, "Player", "getBankBalance", PlayerFunctions::luaPlayerGetBankBalance); - registerMethod(L, "Player", "setBankBalance", PlayerFunctions::luaPlayerSetBankBalance); - - registerMethod(L, "Player", "getStorageValue", PlayerFunctions::luaPlayerGetStorageValue); - registerMethod(L, "Player", "setStorageValue", PlayerFunctions::luaPlayerSetStorageValue); - - registerMethod(L, "Player", "getStorageValueByName", PlayerFunctions::luaPlayerGetStorageValueByName); - registerMethod(L, "Player", "setStorageValueByName", PlayerFunctions::luaPlayerSetStorageValueByName); - - registerMethod(L, "Player", "addItem", PlayerFunctions::luaPlayerAddItem); - registerMethod(L, "Player", "addItemEx", PlayerFunctions::luaPlayerAddItemEx); - registerMethod(L, "Player", "addItemStash", PlayerFunctions::luaPlayerAddItemStash); - registerMethod(L, "Player", "removeStashItem", PlayerFunctions::luaPlayerRemoveStashItem); - registerMethod(L, "Player", "removeItem", PlayerFunctions::luaPlayerRemoveItem); - registerMethod(L, "Player", "sendContainer", PlayerFunctions::luaPlayerSendContainer); - registerMethod(L, "Player", "sendUpdateContainer", PlayerFunctions::luaPlayerSendUpdateContainer); - - registerMethod(L, "Player", "getMoney", PlayerFunctions::luaPlayerGetMoney); - registerMethod(L, "Player", "addMoney", PlayerFunctions::luaPlayerAddMoney); - registerMethod(L, "Player", "removeMoney", PlayerFunctions::luaPlayerRemoveMoney); - - registerMethod(L, "Player", "showTextDialog", PlayerFunctions::luaPlayerShowTextDialog); - - registerMethod(L, "Player", "sendTextMessage", PlayerFunctions::luaPlayerSendTextMessage); - registerMethod(L, "Player", "sendChannelMessage", PlayerFunctions::luaPlayerSendChannelMessage); - registerMethod(L, "Player", "sendPrivateMessage", PlayerFunctions::luaPlayerSendPrivateMessage); - registerMethod(L, "Player", "channelSay", PlayerFunctions::luaPlayerChannelSay); - registerMethod(L, "Player", "openChannel", PlayerFunctions::luaPlayerOpenChannel); - - registerMethod(L, "Player", "getSlotItem", PlayerFunctions::luaPlayerGetSlotItem); - - registerMethod(L, "Player", "getParty", PlayerFunctions::luaPlayerGetParty); - - registerMethod(L, "Player", "addOutfit", PlayerFunctions::luaPlayerAddOutfit); - registerMethod(L, "Player", "addOutfitAddon", PlayerFunctions::luaPlayerAddOutfitAddon); - registerMethod(L, "Player", "removeOutfit", PlayerFunctions::luaPlayerRemoveOutfit); - registerMethod(L, "Player", "removeOutfitAddon", PlayerFunctions::luaPlayerRemoveOutfitAddon); - registerMethod(L, "Player", "hasOutfit", PlayerFunctions::luaPlayerHasOutfit); - registerMethod(L, "Player", "sendOutfitWindow", PlayerFunctions::luaPlayerSendOutfitWindow); - - registerMethod(L, "Player", "addMount", PlayerFunctions::luaPlayerAddMount); - registerMethod(L, "Player", "removeMount", PlayerFunctions::luaPlayerRemoveMount); - registerMethod(L, "Player", "hasMount", PlayerFunctions::luaPlayerHasMount); - - registerMethod(L, "Player", "addFamiliar", PlayerFunctions::luaPlayerAddFamiliar); - registerMethod(L, "Player", "removeFamiliar", PlayerFunctions::luaPlayerRemoveFamiliar); - registerMethod(L, "Player", "hasFamiliar", PlayerFunctions::luaPlayerHasFamiliar); - registerMethod(L, "Player", "setFamiliarLooktype", PlayerFunctions::luaPlayerSetFamiliarLooktype); - registerMethod(L, "Player", "getFamiliarLooktype", PlayerFunctions::luaPlayerGetFamiliarLooktype); - - registerMethod(L, "Player", "getPremiumDays", PlayerFunctions::luaPlayerGetPremiumDays); - registerMethod(L, "Player", "addPremiumDays", PlayerFunctions::luaPlayerAddPremiumDays); - registerMethod(L, "Player", "removePremiumDays", PlayerFunctions::luaPlayerRemovePremiumDays); - - registerMethod(L, "Player", "getTibiaCoins", PlayerFunctions::luaPlayerGetTibiaCoins); - registerMethod(L, "Player", "addTibiaCoins", PlayerFunctions::luaPlayerAddTibiaCoins); - registerMethod(L, "Player", "removeTibiaCoins", PlayerFunctions::luaPlayerRemoveTibiaCoins); - - registerMethod(L, "Player", "getTransferableCoins", PlayerFunctions::luaPlayerGetTransferableCoins); - registerMethod(L, "Player", "addTransferableCoins", PlayerFunctions::luaPlayerAddTransferableCoins); - registerMethod(L, "Player", "removeTransferableCoins", PlayerFunctions::luaPlayerRemoveTransferableCoins); - - registerMethod(L, "Player", "hasBlessing", PlayerFunctions::luaPlayerHasBlessing); - registerMethod(L, "Player", "addBlessing", PlayerFunctions::luaPlayerAddBlessing); - registerMethod(L, "Player", "removeBlessing", PlayerFunctions::luaPlayerRemoveBlessing); - registerMethod(L, "Player", "getBlessingCount", PlayerFunctions::luaPlayerGetBlessingCount); - - registerMethod(L, "Player", "canLearnSpell", PlayerFunctions::luaPlayerCanLearnSpell); - registerMethod(L, "Player", "learnSpell", PlayerFunctions::luaPlayerLearnSpell); - registerMethod(L, "Player", "forgetSpell", PlayerFunctions::luaPlayerForgetSpell); - registerMethod(L, "Player", "hasLearnedSpell", PlayerFunctions::luaPlayerHasLearnedSpell); - - registerMethod(L, "Player", "openImbuementWindow", PlayerFunctions::luaPlayerOpenImbuementWindow); - registerMethod(L, "Player", "closeImbuementWindow", PlayerFunctions::luaPlayerCloseImbuementWindow); - - registerMethod(L, "Player", "sendTutorial", PlayerFunctions::luaPlayerSendTutorial); - registerMethod(L, "Player", "addMapMark", PlayerFunctions::luaPlayerAddMapMark); - - registerMethod(L, "Player", "save", PlayerFunctions::luaPlayerSave); - registerMethod(L, "Player", "popupFYI", PlayerFunctions::luaPlayerPopupFYI); - - registerMethod(L, "Player", "isPzLocked", PlayerFunctions::luaPlayerIsPzLocked); - - registerMethod(L, "Player", "getClient", PlayerFunctions::luaPlayerGetClient); - - registerMethod(L, "Player", "getHouse", PlayerFunctions::luaPlayerGetHouse); - registerMethod(L, "Player", "sendHouseWindow", PlayerFunctions::luaPlayerSendHouseWindow); - registerMethod(L, "Player", "setEditHouse", PlayerFunctions::luaPlayerSetEditHouse); - - registerMethod(L, "Player", "setGhostMode", PlayerFunctions::luaPlayerSetGhostMode); - - registerMethod(L, "Player", "getContainerId", PlayerFunctions::luaPlayerGetContainerId); - registerMethod(L, "Player", "getContainerById", PlayerFunctions::luaPlayerGetContainerById); - registerMethod(L, "Player", "getContainerIndex", PlayerFunctions::luaPlayerGetContainerIndex); - - registerMethod(L, "Player", "getInstantSpells", PlayerFunctions::luaPlayerGetInstantSpells); - registerMethod(L, "Player", "canCast", PlayerFunctions::luaPlayerCanCast); - - registerMethod(L, "Player", "hasChaseMode", PlayerFunctions::luaPlayerHasChaseMode); - registerMethod(L, "Player", "hasSecureMode", PlayerFunctions::luaPlayerHasSecureMode); - registerMethod(L, "Player", "getFightMode", PlayerFunctions::luaPlayerGetFightMode); - - registerMethod(L, "Player", "getBaseXpGain", PlayerFunctions::luaPlayerGetBaseXpGain); - registerMethod(L, "Player", "setBaseXpGain", PlayerFunctions::luaPlayerSetBaseXpGain); - registerMethod(L, "Player", "getVoucherXpBoost", PlayerFunctions::luaPlayerGetVoucherXpBoost); - registerMethod(L, "Player", "setVoucherXpBoost", PlayerFunctions::luaPlayerSetVoucherXpBoost); - registerMethod(L, "Player", "getGrindingXpBoost", PlayerFunctions::luaPlayerGetGrindingXpBoost); - registerMethod(L, "Player", "setGrindingXpBoost", PlayerFunctions::luaPlayerSetGrindingXpBoost); - registerMethod(L, "Player", "getXpBoostPercent", PlayerFunctions::luaPlayerGetXpBoostPercent); - registerMethod(L, "Player", "setXpBoostPercent", PlayerFunctions::luaPlayerSetXpBoostPercent); - registerMethod(L, "Player", "getStaminaXpBoost", PlayerFunctions::luaPlayerGetStaminaXpBoost); - registerMethod(L, "Player", "setStaminaXpBoost", PlayerFunctions::luaPlayerSetStaminaXpBoost); - registerMethod(L, "Player", "getXpBoostTime", PlayerFunctions::luaPlayerGetXpBoostTime); - registerMethod(L, "Player", "setXpBoostTime", PlayerFunctions::luaPlayerSetXpBoostTime); - - registerMethod(L, "Player", "getIdleTime", PlayerFunctions::luaPlayerGetIdleTime); - registerMethod(L, "Player", "getFreeBackpackSlots", PlayerFunctions::luaPlayerGetFreeBackpackSlots); - - registerMethod(L, "Player", "isOffline", PlayerFunctions::luaPlayerIsOffline); - - registerMethod(L, "Player", "openMarket", PlayerFunctions::luaPlayerOpenMarket); - - registerMethod(L, "Player", "instantSkillWOD", PlayerFunctions::luaPlayerInstantSkillWOD); - registerMethod(L, "Player", "upgradeSpellsWOD", PlayerFunctions::luaPlayerUpgradeSpellWOD); - registerMethod(L, "Player", "revelationStageWOD", PlayerFunctions::luaPlayerRevelationStageWOD); - registerMethod(L, "Player", "reloadData", PlayerFunctions::luaPlayerReloadData); - registerMethod(L, "Player", "onThinkWheelOfDestiny", PlayerFunctions::luaPlayerOnThinkWheelOfDestiny); - registerMethod(L, "Player", "avatarTimer", PlayerFunctions::luaPlayerAvatarTimer); - registerMethod(L, "Player", "getWheelSpellAdditionalArea", PlayerFunctions::luaPlayerGetWheelSpellAdditionalArea); - registerMethod(L, "Player", "getWheelSpellAdditionalTarget", PlayerFunctions::luaPlayerGetWheelSpellAdditionalTarget); - registerMethod(L, "Player", "getWheelSpellAdditionalDuration", PlayerFunctions::luaPlayerGetWheelSpellAdditionalDuration); - - // Forge Functions - registerMethod(L, "Player", "openForge", PlayerFunctions::luaPlayerOpenForge); - registerMethod(L, "Player", "closeForge", PlayerFunctions::luaPlayerCloseForge); - - registerMethod(L, "Player", "addForgeDusts", PlayerFunctions::luaPlayerAddForgeDusts); - registerMethod(L, "Player", "removeForgeDusts", PlayerFunctions::luaPlayerRemoveForgeDusts); - registerMethod(L, "Player", "getForgeDusts", PlayerFunctions::luaPlayerGetForgeDusts); - registerMethod(L, "Player", "setForgeDusts", PlayerFunctions::luaPlayerSetForgeDusts); - - registerMethod(L, "Player", "addForgeDustLevel", PlayerFunctions::luaPlayerAddForgeDustLevel); - registerMethod(L, "Player", "removeForgeDustLevel", PlayerFunctions::luaPlayerRemoveForgeDustLevel); - registerMethod(L, "Player", "getForgeDustLevel", PlayerFunctions::luaPlayerGetForgeDustLevel); - - registerMethod(L, "Player", "getForgeSlivers", PlayerFunctions::luaPlayerGetForgeSlivers); - registerMethod(L, "Player", "getForgeCores", PlayerFunctions::luaPlayerGetForgeCores); - registerMethod(L, "Player", "isUIExhausted", PlayerFunctions::luaPlayerIsUIExhausted); - registerMethod(L, "Player", "updateUIExhausted", PlayerFunctions::luaPlayerUpdateUIExhausted); - - registerMethod(L, "Player", "setFaction", PlayerFunctions::luaPlayerSetFaction); - registerMethod(L, "Player", "getFaction", PlayerFunctions::luaPlayerGetFaction); - - // Bosstiary Functions - registerMethod(L, "Player", "getBosstiaryLevel", PlayerFunctions::luaPlayerGetBosstiaryLevel); - registerMethod(L, "Player", "getBosstiaryKills", PlayerFunctions::luaPlayerGetBosstiaryKills); - registerMethod(L, "Player", "addBosstiaryKill", PlayerFunctions::luaPlayerAddBosstiaryKill); - registerMethod(L, "Player", "setBossPoints", PlayerFunctions::luaPlayerSetBossPoints); - registerMethod(L, "Player", "setRemoveBossTime", PlayerFunctions::luaPlayerSetRemoveBossTime); - registerMethod(L, "Player", "getSlotBossId", PlayerFunctions::luaPlayerGetSlotBossId); - registerMethod(L, "Player", "getBossBonus", PlayerFunctions::luaPlayerGetBossBonus); - registerMethod(L, "Player", "sendBosstiaryCooldownTimer", PlayerFunctions::luaPlayerBosstiaryCooldownTimer); - - registerMethod(L, "Player", "sendSingleSoundEffect", PlayerFunctions::luaPlayerSendSingleSoundEffect); - registerMethod(L, "Player", "sendDoubleSoundEffect", PlayerFunctions::luaPlayerSendDoubleSoundEffect); - - registerMethod(L, "Player", "getName", PlayerFunctions::luaPlayerGetName); - registerMethod(L, "Player", "changeName", PlayerFunctions::luaPlayerChangeName); - - registerMethod(L, "Player", "hasGroupFlag", PlayerFunctions::luaPlayerHasGroupFlag); - registerMethod(L, "Player", "setGroupFlag", PlayerFunctions::luaPlayerSetGroupFlag); - registerMethod(L, "Player", "removeGroupFlag", PlayerFunctions::luaPlayerRemoveGroupFlag); - - registerMethod(L, "Player", "setHazardSystemPoints", PlayerFunctions::luaPlayerAddHazardSystemPoints); - registerMethod(L, "Player", "getHazardSystemPoints", PlayerFunctions::luaPlayerGetHazardSystemPoints); - - registerMethod(L, "Player", "setLoyaltyBonus", PlayerFunctions::luaPlayerSetLoyaltyBonus); - registerMethod(L, "Player", "getLoyaltyBonus", PlayerFunctions::luaPlayerGetLoyaltyBonus); - registerMethod(L, "Player", "getLoyaltyPoints", PlayerFunctions::luaPlayerGetLoyaltyPoints); - registerMethod(L, "Player", "getLoyaltyTitle", PlayerFunctions::luaPlayerGetLoyaltyTitle); - registerMethod(L, "Player", "setLoyaltyTitle", PlayerFunctions::luaPlayerSetLoyaltyTitle); - - registerMethod(L, "Player", "updateConcoction", PlayerFunctions::luaPlayerUpdateConcoction); - registerMethod(L, "Player", "clearSpellCooldowns", PlayerFunctions::luaPlayerClearSpellCooldowns); - - registerMethod(L, "Player", "isVip", PlayerFunctions::luaPlayerIsVip); - registerMethod(L, "Player", "getVipDays", PlayerFunctions::luaPlayerGetVipDays); - registerMethod(L, "Player", "getVipTime", PlayerFunctions::luaPlayerGetVipTime); - - registerMethod(L, "Player", "kv", PlayerFunctions::luaPlayerKV); - registerMethod(L, "Player", "getStoreInbox", PlayerFunctions::luaPlayerGetStoreInbox); - - registerMethod(L, "Player", "hasAchievement", PlayerFunctions::luaPlayerHasAchievement); - registerMethod(L, "Player", "addAchievement", PlayerFunctions::luaPlayerAddAchievement); - registerMethod(L, "Player", "removeAchievement", PlayerFunctions::luaPlayerRemoveAchievement); - registerMethod(L, "Player", "getAchievementPoints", PlayerFunctions::luaPlayerGetAchievementPoints); - registerMethod(L, "Player", "addAchievementPoints", PlayerFunctions::luaPlayerAddAchievementPoints); - registerMethod(L, "Player", "removeAchievementPoints", PlayerFunctions::luaPlayerRemoveAchievementPoints); - - // Badge Functions - registerMethod(L, "Player", "addBadge", PlayerFunctions::luaPlayerAddBadge); - - // Title Functions - registerMethod(L, "Player", "addTitle", PlayerFunctions::luaPlayerAddTitle); - registerMethod(L, "Player", "getTitles", PlayerFunctions::luaPlayerGetTitles); - registerMethod(L, "Player", "setCurrentTitle", PlayerFunctions::luaPlayerSetCurrentTitle); - - // Store Summary - registerMethod(L, "Player", "createTransactionSummary", PlayerFunctions::luaPlayerCreateTransactionSummary); - - registerMethod(L, "Player", "takeScreenshot", PlayerFunctions::luaPlayerTakeScreenshot); - registerMethod(L, "Player", "sendIconBakragore", PlayerFunctions::luaPlayerSendIconBakragore); - registerMethod(L, "Player", "removeIconBakragore", PlayerFunctions::luaPlayerRemoveIconBakragore); - registerMethod(L, "Player", "sendCreatureAppear", PlayerFunctions::luaPlayerSendCreatureAppear); - - GroupFunctions::init(L); - GuildFunctions::init(L); - MountFunctions::init(L); - PartyFunctions::init(L); - VocationFunctions::init(L); - } +class PlayerFunctions { + static void init(lua_State* L); static int luaPlayerCreate(lua_State* L); @@ -595,6 +229,7 @@ class PlayerFunctions final : LuaScriptInterface { static int luaPlayerAddTransferableCoins(lua_State* L); static int luaPlayerRemoveTransferableCoins(lua_State* L); + static int luaPlayerSendBlessStatus(lua_State* L); static int luaPlayerHasBlessing(lua_State* L); static int luaPlayerAddBlessing(lua_State* L); static int luaPlayerRemoveBlessing(lua_State* L); diff --git a/src/lua/functions/creatures/player/vocation_functions.cpp b/src/lua/functions/creatures/player/vocation_functions.cpp index 15e1603cc54..166e000f433 100644 --- a/src/lua/functions/creatures/player/vocation_functions.cpp +++ b/src/lua/functions/creatures/player/vocation_functions.cpp @@ -7,22 +7,58 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/players/vocations/vocation.hpp" #include "lua/functions/creatures/player/vocation_functions.hpp" +#include "creatures/players/vocations/vocation.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void VocationFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Vocation", "", VocationFunctions::luaVocationCreate); + Lua::registerMetaMethod(L, "Vocation", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Vocation", "getId", VocationFunctions::luaVocationGetId); + Lua::registerMethod(L, "Vocation", "getClientId", VocationFunctions::luaVocationGetClientId); + Lua::registerMethod(L, "Vocation", "getBaseId", VocationFunctions::luaVocationGetBaseId); + Lua::registerMethod(L, "Vocation", "getName", VocationFunctions::luaVocationGetName); + Lua::registerMethod(L, "Vocation", "getDescription", VocationFunctions::luaVocationGetDescription); + + Lua::registerMethod(L, "Vocation", "getRequiredSkillTries", VocationFunctions::luaVocationGetRequiredSkillTries); + Lua::registerMethod(L, "Vocation", "getRequiredManaSpent", VocationFunctions::luaVocationGetRequiredManaSpent); + + Lua::registerMethod(L, "Vocation", "getCapacityGain", VocationFunctions::luaVocationGetCapacityGain); + + Lua::registerMethod(L, "Vocation", "getHealthGain", VocationFunctions::luaVocationGetHealthGain); + Lua::registerMethod(L, "Vocation", "getHealthGainTicks", VocationFunctions::luaVocationGetHealthGainTicks); + Lua::registerMethod(L, "Vocation", "getHealthGainAmount", VocationFunctions::luaVocationGetHealthGainAmount); + + Lua::registerMethod(L, "Vocation", "getManaGain", VocationFunctions::luaVocationGetManaGain); + Lua::registerMethod(L, "Vocation", "getManaGainTicks", VocationFunctions::luaVocationGetManaGainTicks); + Lua::registerMethod(L, "Vocation", "getManaGainAmount", VocationFunctions::luaVocationGetManaGainAmount); + + Lua::registerMethod(L, "Vocation", "getMaxSoul", VocationFunctions::luaVocationGetMaxSoul); + Lua::registerMethod(L, "Vocation", "getSoulGainTicks", VocationFunctions::luaVocationGetSoulGainTicks); + + Lua::registerMethod(L, "Vocation", "getBaseAttackSpeed", VocationFunctions::luaVocationGetBaseAttackSpeed); + Lua::registerMethod(L, "Vocation", "getAttackSpeed", VocationFunctions::luaVocationGetAttackSpeed); + Lua::registerMethod(L, "Vocation", "getBaseSpeed", VocationFunctions::luaVocationGetBaseSpeed); + + Lua::registerMethod(L, "Vocation", "getDemotion", VocationFunctions::luaVocationGetDemotion); + Lua::registerMethod(L, "Vocation", "getPromotion", VocationFunctions::luaVocationGetPromotion); +} + int VocationFunctions::luaVocationCreate(lua_State* L) { // Vocation(id or name) uint16_t vocationId; - if (isNumber(L, 2)) { - vocationId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + vocationId = Lua::getNumber<uint16_t>(L, 2); } else { - vocationId = g_vocations().getVocationId(getString(L, 2)); + vocationId = g_vocations().getVocationId(Lua::getString(L, 2)); } - std::shared_ptr<Vocation> vocation = g_vocations().getVocation(vocationId); + const auto &vocation = g_vocations().getVocation(vocationId); if (vocation) { - pushUserdata<Vocation>(L, vocation); - setMetatable(L, -1, "Vocation"); + Lua::pushUserdata<Vocation>(L, vocation); + Lua::setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } @@ -31,7 +67,7 @@ int VocationFunctions::luaVocationCreate(lua_State* L) { int VocationFunctions::luaVocationGetId(lua_State* L) { // vocation:getId() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getId()); } else { @@ -42,7 +78,7 @@ int VocationFunctions::luaVocationGetId(lua_State* L) { int VocationFunctions::luaVocationGetClientId(lua_State* L) { // vocation:getClientId() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getClientId()); } else { @@ -53,7 +89,7 @@ int VocationFunctions::luaVocationGetClientId(lua_State* L) { int VocationFunctions::luaVocationGetBaseId(lua_State* L) { // vocation:getBaseId() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getBaseId()); } else { @@ -64,9 +100,9 @@ int VocationFunctions::luaVocationGetBaseId(lua_State* L) { int VocationFunctions::luaVocationGetName(lua_State* L) { // vocation:getName() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { - pushString(L, vocation->getVocName()); + Lua::pushString(L, vocation->getVocName()); } else { lua_pushnil(L); } @@ -75,9 +111,9 @@ int VocationFunctions::luaVocationGetName(lua_State* L) { int VocationFunctions::luaVocationGetDescription(lua_State* L) { // vocation:getDescription() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { - pushString(L, vocation->getVocDescription()); + Lua::pushString(L, vocation->getVocDescription()); } else { lua_pushnil(L); } @@ -86,10 +122,10 @@ int VocationFunctions::luaVocationGetDescription(lua_State* L) { int VocationFunctions::luaVocationGetRequiredSkillTries(lua_State* L) { // vocation:getRequiredSkillTries(skillType, skillLevel) - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { - skills_t skillType = getNumber<skills_t>(L, 2); - uint16_t skillLevel = getNumber<uint16_t>(L, 3); + const skills_t skillType = Lua::getNumber<skills_t>(L, 2); + const uint16_t skillLevel = Lua::getNumber<uint16_t>(L, 3); lua_pushnumber(L, vocation->getReqSkillTries(skillType, skillLevel)); } else { lua_pushnil(L); @@ -99,9 +135,9 @@ int VocationFunctions::luaVocationGetRequiredSkillTries(lua_State* L) { int VocationFunctions::luaVocationGetRequiredManaSpent(lua_State* L) { // vocation:getRequiredManaSpent(magicLevel) - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { - uint32_t magicLevel = getNumber<uint32_t>(L, 2); + const uint32_t magicLevel = Lua::getNumber<uint32_t>(L, 2); lua_pushnumber(L, vocation->getReqMana(magicLevel)); } else { lua_pushnil(L); @@ -111,7 +147,7 @@ int VocationFunctions::luaVocationGetRequiredManaSpent(lua_State* L) { int VocationFunctions::luaVocationGetCapacityGain(lua_State* L) { // vocation:getCapacityGain() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getCapGain()); } else { @@ -122,7 +158,7 @@ int VocationFunctions::luaVocationGetCapacityGain(lua_State* L) { int VocationFunctions::luaVocationGetHealthGain(lua_State* L) { // vocation:getHealthGain() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHPGain()); } else { @@ -133,7 +169,7 @@ int VocationFunctions::luaVocationGetHealthGain(lua_State* L) { int VocationFunctions::luaVocationGetHealthGainTicks(lua_State* L) { // vocation:getHealthGainTicks() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHealthGainTicks()); } else { @@ -144,7 +180,7 @@ int VocationFunctions::luaVocationGetHealthGainTicks(lua_State* L) { int VocationFunctions::luaVocationGetHealthGainAmount(lua_State* L) { // vocation:getHealthGainAmount() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHealthGainAmount()); } else { @@ -155,7 +191,7 @@ int VocationFunctions::luaVocationGetHealthGainAmount(lua_State* L) { int VocationFunctions::luaVocationGetManaGain(lua_State* L) { // vocation:getManaGain() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGain()); } else { @@ -166,7 +202,7 @@ int VocationFunctions::luaVocationGetManaGain(lua_State* L) { int VocationFunctions::luaVocationGetManaGainTicks(lua_State* L) { // vocation:getManaGainTicks() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGainTicks()); } else { @@ -177,7 +213,7 @@ int VocationFunctions::luaVocationGetManaGainTicks(lua_State* L) { int VocationFunctions::luaVocationGetManaGainAmount(lua_State* L) { // vocation:getManaGainAmount() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGainAmount()); } else { @@ -188,7 +224,7 @@ int VocationFunctions::luaVocationGetManaGainAmount(lua_State* L) { int VocationFunctions::luaVocationGetMaxSoul(lua_State* L) { // vocation:getMaxSoul() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getSoulMax()); } else { @@ -199,7 +235,7 @@ int VocationFunctions::luaVocationGetMaxSoul(lua_State* L) { int VocationFunctions::luaVocationGetSoulGainTicks(lua_State* L) { // vocation:getSoulGainTicks() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getSoulGainTicks()); } else { @@ -210,7 +246,7 @@ int VocationFunctions::luaVocationGetSoulGainTicks(lua_State* L) { int VocationFunctions::luaVocationGetBaseAttackSpeed(lua_State* L) { // vocation:getBaseAttackSpeed() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getBaseAttackSpeed()); } else { @@ -221,7 +257,7 @@ int VocationFunctions::luaVocationGetBaseAttackSpeed(lua_State* L) { int VocationFunctions::luaVocationGetAttackSpeed(lua_State* L) { // vocation:getAttackSpeed() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getAttackSpeed()); } else { @@ -232,7 +268,7 @@ int VocationFunctions::luaVocationGetAttackSpeed(lua_State* L) { int VocationFunctions::luaVocationGetBaseSpeed(lua_State* L) { // vocation:getBaseSpeed() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (vocation) { lua_pushnumber(L, vocation->getBaseSpeed()); } else { @@ -243,22 +279,22 @@ int VocationFunctions::luaVocationGetBaseSpeed(lua_State* L) { int VocationFunctions::luaVocationGetDemotion(lua_State* L) { // vocation:getDemotion() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (!vocation) { lua_pushnil(L); return 1; } - uint16_t fromId = vocation->getFromVocation(); + const uint16_t fromId = vocation->getFromVocation(); if (fromId == VOCATION_NONE) { lua_pushnil(L); return 1; } - std::shared_ptr<Vocation> demotedVocation = g_vocations().getVocation(fromId); + const auto &demotedVocation = g_vocations().getVocation(fromId); if (demotedVocation && demotedVocation != vocation) { - pushUserdata<Vocation>(L, demotedVocation); - setMetatable(L, -1, "Vocation"); + Lua::pushUserdata<Vocation>(L, demotedVocation); + Lua::setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } @@ -267,22 +303,22 @@ int VocationFunctions::luaVocationGetDemotion(lua_State* L) { int VocationFunctions::luaVocationGetPromotion(lua_State* L) { // vocation:getPromotion() - std::shared_ptr<Vocation> vocation = getUserdataShared<Vocation>(L, 1); + const auto &vocation = Lua::getUserdataShared<Vocation>(L, 1); if (!vocation) { lua_pushnil(L); return 1; } - uint16_t promotedId = g_vocations().getPromotedVocation(vocation->getId()); + const uint16_t promotedId = g_vocations().getPromotedVocation(vocation->getId()); if (promotedId == VOCATION_NONE) { lua_pushnil(L); return 1; } - std::shared_ptr<Vocation> promotedVocation = g_vocations().getVocation(promotedId); + const auto &promotedVocation = g_vocations().getVocation(promotedId); if (promotedVocation && promotedVocation != vocation) { - pushUserdata<Vocation>(L, promotedVocation); - setMetatable(L, -1, "Vocation"); + Lua::pushUserdata<Vocation>(L, promotedVocation); + Lua::setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } diff --git a/src/lua/functions/creatures/player/vocation_functions.hpp b/src/lua/functions/creatures/player/vocation_functions.hpp index 0895f6ac8d6..10c9364680d 100644 --- a/src/lua/functions/creatures/player/vocation_functions.hpp +++ b/src/lua/functions/creatures/player/vocation_functions.hpp @@ -9,43 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class VocationFunctions final : LuaScriptInterface { +class VocationFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Vocation", "", VocationFunctions::luaVocationCreate); - registerMetaMethod(L, "Vocation", "__eq", VocationFunctions::luaUserdataCompare); - - registerMethod(L, "Vocation", "getId", VocationFunctions::luaVocationGetId); - registerMethod(L, "Vocation", "getClientId", VocationFunctions::luaVocationGetClientId); - registerMethod(L, "Vocation", "getBaseId", VocationFunctions::luaVocationGetBaseId); - registerMethod(L, "Vocation", "getName", VocationFunctions::luaVocationGetName); - registerMethod(L, "Vocation", "getDescription", VocationFunctions::luaVocationGetDescription); - - registerMethod(L, "Vocation", "getRequiredSkillTries", VocationFunctions::luaVocationGetRequiredSkillTries); - registerMethod(L, "Vocation", "getRequiredManaSpent", VocationFunctions::luaVocationGetRequiredManaSpent); - - registerMethod(L, "Vocation", "getCapacityGain", VocationFunctions::luaVocationGetCapacityGain); - - registerMethod(L, "Vocation", "getHealthGain", VocationFunctions::luaVocationGetHealthGain); - registerMethod(L, "Vocation", "getHealthGainTicks", VocationFunctions::luaVocationGetHealthGainTicks); - registerMethod(L, "Vocation", "getHealthGainAmount", VocationFunctions::luaVocationGetHealthGainAmount); - - registerMethod(L, "Vocation", "getManaGain", VocationFunctions::luaVocationGetManaGain); - registerMethod(L, "Vocation", "getManaGainTicks", VocationFunctions::luaVocationGetManaGainTicks); - registerMethod(L, "Vocation", "getManaGainAmount", VocationFunctions::luaVocationGetManaGainAmount); - - registerMethod(L, "Vocation", "getMaxSoul", VocationFunctions::luaVocationGetMaxSoul); - registerMethod(L, "Vocation", "getSoulGainTicks", VocationFunctions::luaVocationGetSoulGainTicks); - - registerMethod(L, "Vocation", "getBaseAttackSpeed", VocationFunctions::luaVocationGetBaseAttackSpeed); - registerMethod(L, "Vocation", "getAttackSpeed", VocationFunctions::luaVocationGetAttackSpeed); - registerMethod(L, "Vocation", "getBaseSpeed", VocationFunctions::luaVocationGetBaseSpeed); - - registerMethod(L, "Vocation", "getDemotion", VocationFunctions::luaVocationGetDemotion); - registerMethod(L, "Vocation", "getPromotion", VocationFunctions::luaVocationGetPromotion); - } + static void init(lua_State* L); private: static int luaVocationCreate(lua_State* L); diff --git a/src/lua/functions/events/action_functions.cpp b/src/lua/functions/events/action_functions.cpp index c5cf4c73c29..39ca0939150 100644 --- a/src/lua/functions/events/action_functions.cpp +++ b/src/lua/functions/events/action_functions.cpp @@ -7,109 +7,124 @@ * Website: https://docs.opentibiabr.com/ */ -#include "lua/creature/actions.hpp" #include "lua/functions/events/action_functions.hpp" + +#include "lua/creature/actions.hpp" #include "game/game.hpp" #include "items/item.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ActionFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Action", "", ActionFunctions::luaCreateAction); + Lua::registerMethod(L, "Action", "onUse", ActionFunctions::luaActionOnUse); + Lua::registerMethod(L, "Action", "register", ActionFunctions::luaActionRegister); + Lua::registerMethod(L, "Action", "id", ActionFunctions::luaActionItemId); + Lua::registerMethod(L, "Action", "aid", ActionFunctions::luaActionActionId); + Lua::registerMethod(L, "Action", "uid", ActionFunctions::luaActionUniqueId); + Lua::registerMethod(L, "Action", "position", ActionFunctions::luaActionPosition); + Lua::registerMethod(L, "Action", "allowFarUse", ActionFunctions::luaActionAllowFarUse); + Lua::registerMethod(L, "Action", "blockWalls", ActionFunctions::luaActionBlockWalls); + Lua::registerMethod(L, "Action", "checkFloor", ActionFunctions::luaActionCheckFloor); + Lua::registerMethod(L, "Action", "position", ActionFunctions::luaActionPosition); +} int ActionFunctions::luaCreateAction(lua_State* L) { // Action() - auto action = std::make_shared<Action>(getScriptEnv()->getScriptInterface()); - pushUserdata<Action>(L, action); - setMetatable(L, -1, "Action"); + const auto action = std::make_shared<Action>(); + Lua::pushUserdata<Action>(L, action); + Lua::setMetatable(L, -1, "Action"); return 1; } int ActionFunctions::luaActionOnUse(lua_State* L) { // action:onUse(callback) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - if (!action->loadCallback()) { - pushBoolean(L, false); + if (!action->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - action->setLoadedCallback(true); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionRegister(lua_State* L) { // action:register() - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - if (!action->isLoadedCallback()) { - pushBoolean(L, false); + if (!action->isLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_actions().registerLuaEvent(action)); - pushBoolean(L, true); + Lua::pushBoolean(L, g_actions().registerLuaEvent(action)); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionItemId(lua_State* L) { // action:id(ids) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - action->setItemIdsVector(getNumber<uint16_t>(L, 2 + i)); + action->setItemIdsVector(Lua::getNumber<uint16_t>(L, 2 + i)); } } else { - action->setItemIdsVector(getNumber<uint16_t>(L, 2)); + action->setItemIdsVector(Lua::getNumber<uint16_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionActionId(lua_State* L) { // action:aid(aids) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - action->setActionIdsVector(getNumber<uint16_t>(L, 2 + i)); + action->setActionIdsVector(Lua::getNumber<uint16_t>(L, 2 + i)); } } else { - action->setActionIdsVector(getNumber<uint16_t>(L, 2)); + action->setActionIdsVector(Lua::getNumber<uint16_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionUniqueId(lua_State* L) { // action:uid(uids) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - action->setUniqueIdsVector(getNumber<uint16_t>(L, 2 + i)); + action->setUniqueIdsVector(Lua::getNumber<uint16_t>(L, 2 + i)); } } else { - action->setUniqueIdsVector(getNumber<uint16_t>(L, 2)); + action->setUniqueIdsVector(Lua::getNumber<uint16_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } @@ -120,20 +135,20 @@ int ActionFunctions::luaActionPosition(lua_State* L) { * @param itemId or @param itemName = if item id or string name is set, the item is created on position (if not exists), this variable is nil by default * action:position(positions, itemId or name) */ - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (!action) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - Position position = getPosition(L, 2); + const Position position = Lua::getPosition(L, 2); // The parameter "- 1" because self is a parameter aswell, which we want to skip L 1 (UserData) - // isNumber(L, 2) is for skip the itemId - if (int parameters = lua_gettop(L) - 1; - parameters > 1 && isNumber(L, 2)) { + // Lua::isNumber(L, 2) is for skip the itemId + if (const int parameters = lua_gettop(L) - 1; + parameters > 1 && Lua::isNumber(L, 2)) { for (int i = 0; i < parameters; ++i) { - action->setPositionsVector(getPosition(L, 2 + i)); + action->setPositionsVector(Lua::getPosition(L, 2 + i)); } } else { action->setPositionsVector(position); @@ -141,14 +156,14 @@ int ActionFunctions::luaActionPosition(lua_State* L) { uint16_t itemId; bool createItem = false; - if (isNumber(L, 3)) { - itemId = getNumber<uint16_t>(L, 3); + if (Lua::isNumber(L, 3)) { + itemId = Lua::getNumber<uint16_t>(L, 3); createItem = true; - } else if (isString(L, 3)) { - itemId = Item::items.getItemIdByName(getString(L, 3)); + } else if (Lua::isString(L, 3)) { + itemId = Item::items.getItemIdByName(Lua::getString(L, 3)); if (itemId == 0) { - reportErrorFunc("Not found item with name: " + getString(L, 3)); - pushBoolean(L, false); + Lua::reportErrorFunc("Not found item with name: " + Lua::getString(L, 3)); + Lua::pushBoolean(L, false); return 1; } @@ -157,8 +172,8 @@ int ActionFunctions::luaActionPosition(lua_State* L) { if (createItem) { if (!Item::items.hasItemType(itemId)) { - reportErrorFunc("Not found item with id: " + itemId); - pushBoolean(L, false); + Lua::reportErrorFunc("Not found item with id: " + itemId); + Lua::pushBoolean(L, false); return 1; } @@ -171,45 +186,45 @@ int ActionFunctions::luaActionPosition(lua_State* L) { g_game().setCreateLuaItems(position, itemId); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ActionFunctions::luaActionAllowFarUse(lua_State* L) { // action:allowFarUse(bool) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - action->setAllowFarUse(getBoolean(L, 2)); - pushBoolean(L, true); + action->setAllowFarUse(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionBlockWalls(lua_State* L) { // action:blockWalls(bool) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - action->setCheckLineOfSight(getBoolean(L, 2)); - pushBoolean(L, true); + action->setCheckLineOfSight(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } int ActionFunctions::luaActionCheckFloor(lua_State* L) { // action:checkFloor(bool) - const auto action = getUserdataShared<Action>(L, 1); + const auto &action = Lua::getUserdataShared<Action>(L, 1); if (action) { - action->setCheckFloor(getBoolean(L, 2)); - pushBoolean(L, true); + action->setCheckFloor(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); } return 1; } diff --git a/src/lua/functions/events/action_functions.hpp b/src/lua/functions/events/action_functions.hpp index 952ee746a5a..e72b65bf726 100644 --- a/src/lua/functions/events/action_functions.hpp +++ b/src/lua/functions/events/action_functions.hpp @@ -9,23 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ActionFunctions final : LuaScriptInterface { +class ActionFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Action", "", ActionFunctions::luaCreateAction); - registerMethod(L, "Action", "onUse", ActionFunctions::luaActionOnUse); - registerMethod(L, "Action", "register", ActionFunctions::luaActionRegister); - registerMethod(L, "Action", "id", ActionFunctions::luaActionItemId); - registerMethod(L, "Action", "aid", ActionFunctions::luaActionActionId); - registerMethod(L, "Action", "uid", ActionFunctions::luaActionUniqueId); - registerMethod(L, "Action", "position", ActionFunctions::luaActionPosition); - registerMethod(L, "Action", "allowFarUse", ActionFunctions::luaActionAllowFarUse); - registerMethod(L, "Action", "blockWalls", ActionFunctions::luaActionBlockWalls); - registerMethod(L, "Action", "checkFloor", ActionFunctions::luaActionCheckFloor); - registerMethod(L, "Action", "position", ActionFunctions::luaActionPosition); - } + static void init(lua_State* L); private: static int luaCreateAction(lua_State* L); diff --git a/src/lua/functions/events/creature_event_functions.cpp b/src/lua/functions/events/creature_event_functions.cpp index ddba9f153fd..6f67375d3eb 100644 --- a/src/lua/functions/events/creature_event_functions.cpp +++ b/src/lua/functions/events/creature_event_functions.cpp @@ -7,25 +7,45 @@ * Website: https://docs.opentibiabr.com/ */ -#include "lua/creature/creatureevent.hpp" #include "lua/functions/events/creature_event_functions.hpp" + +#include "lua/creature/creatureevent.hpp" #include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void CreatureEventFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "CreatureEvent", "", CreatureEventFunctions::luaCreateCreatureEvent); + Lua::registerMethod(L, "CreatureEvent", "type", CreatureEventFunctions::luaCreatureEventType); + Lua::registerMethod(L, "CreatureEvent", "register", CreatureEventFunctions::luaCreatureEventRegister); + Lua::registerMethod(L, "CreatureEvent", "onLogin", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onLogout", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onThink", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onPrepareDeath", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onDeath", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onKill", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onAdvance", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onModalWindow", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onTextEdit", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onHealthChange", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onManaChange", CreatureEventFunctions::luaCreatureEventOnCallback); + Lua::registerMethod(L, "CreatureEvent", "onExtendedOpcode", CreatureEventFunctions::luaCreatureEventOnCallback); +} int CreatureEventFunctions::luaCreateCreatureEvent(lua_State* L) { // CreatureEvent(eventName) - auto creatureEvent = std::make_shared<CreatureEvent>(getScriptEnv()->getScriptInterface()); - creatureEvent->setName(getString(L, 2)); - pushUserdata<CreatureEvent>(L, creatureEvent); - setMetatable(L, -1, "CreatureEvent"); + const auto creatureEvent = std::make_shared<CreatureEvent>(); + creatureEvent->setName(Lua::getString(L, 2)); + Lua::pushUserdata<CreatureEvent>(L, creatureEvent); + Lua::setMetatable(L, -1, "CreatureEvent"); return 1; } int CreatureEventFunctions::luaCreatureEventType(lua_State* L) { // creatureevent:type(callback) - const auto creatureEvent = getUserdataShared<CreatureEvent>(L, 1); + const auto &creatureEvent = Lua::getUserdataShared<CreatureEvent>(L, 1); if (creatureEvent) { - std::string typeName = getString(L, 2); - std::string tmpStr = asLowerCaseString(typeName); + std::string typeName = Lua::getString(L, 2); + const std::string tmpStr = asLowerCaseString(typeName); if (tmpStr == "login") { creatureEvent->setEventType(CREATURE_EVENT_LOGIN); } else if (tmpStr == "logout") { @@ -54,10 +74,10 @@ int CreatureEventFunctions::luaCreatureEventType(lua_State* L) { g_logger().error("[CreatureEventFunctions::luaCreatureEventType] - " "Invalid type for creature event: {}", typeName); - pushBoolean(L, false); + Lua::pushBoolean(L, false); } creatureEvent->setLoaded(true); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -66,13 +86,13 @@ int CreatureEventFunctions::luaCreatureEventType(lua_State* L) { int CreatureEventFunctions::luaCreatureEventRegister(lua_State* L) { // creatureevent:register() - const auto creatureEvent = getUserdataShared<CreatureEvent>(L, 1); + const auto &creatureEvent = Lua::getUserdataShared<CreatureEvent>(L, 1); if (creatureEvent) { - if (!creatureEvent->isLoadedCallback()) { - pushBoolean(L, false); + if (!creatureEvent->isLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_creatureEvents().registerLuaEvent(creatureEvent)); + Lua::pushBoolean(L, g_creatureEvents().registerLuaEvent(creatureEvent)); } else { lua_pushnil(L); } @@ -81,13 +101,13 @@ int CreatureEventFunctions::luaCreatureEventRegister(lua_State* L) { int CreatureEventFunctions::luaCreatureEventOnCallback(lua_State* L) { // creatureevent:onLogin / logout / etc. (callback) - const auto creatureEvent = getUserdataShared<CreatureEvent>(L, 1); + const auto &creatureEvent = Lua::getUserdataShared<CreatureEvent>(L, 1); if (creatureEvent) { - if (!creatureEvent->loadCallback()) { - pushBoolean(L, false); + if (!creatureEvent->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/events/creature_event_functions.hpp b/src/lua/functions/events/creature_event_functions.hpp index 64b9e6e4eb8..be896a495ec 100644 --- a/src/lua/functions/events/creature_event_functions.hpp +++ b/src/lua/functions/events/creature_event_functions.hpp @@ -9,27 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class CreatureEventFunctions final : LuaScriptInterface { +class CreatureEventFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "CreatureEvent", "", CreatureEventFunctions::luaCreateCreatureEvent); - registerMethod(L, "CreatureEvent", "type", CreatureEventFunctions::luaCreatureEventType); - registerMethod(L, "CreatureEvent", "register", CreatureEventFunctions::luaCreatureEventRegister); - registerMethod(L, "CreatureEvent", "onLogin", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onLogout", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onThink", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onPrepareDeath", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onDeath", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onKill", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onAdvance", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onModalWindow", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onTextEdit", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onHealthChange", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onManaChange", CreatureEventFunctions::luaCreatureEventOnCallback); - registerMethod(L, "CreatureEvent", "onExtendedOpcode", CreatureEventFunctions::luaCreatureEventOnCallback); - } + static void init(lua_State* L); private: static int luaCreateCreatureEvent(lua_State* L); diff --git a/src/lua/functions/events/event_callback_functions.cpp b/src/lua/functions/events/event_callback_functions.cpp index c00300b5f47..bec82177256 100644 --- a/src/lua/functions/events/event_callback_functions.cpp +++ b/src/lua/functions/events/event_callback_functions.cpp @@ -14,6 +14,7 @@ #include "utils/tools.hpp" #include "items/item.hpp" #include "creatures/players/player.hpp" +#include "lua/functions/lua_functions_loader.hpp" /** * @class EventCallbackFunctions @@ -26,33 +27,33 @@ */ void EventCallbackFunctions::init(lua_State* luaState) { - registerSharedClass(luaState, "EventCallback", "", EventCallbackFunctions::luaEventCallbackCreate); - registerMethod(luaState, "EventCallback", "type", EventCallbackFunctions::luaEventCallbackType); - registerMethod(luaState, "EventCallback", "register", EventCallbackFunctions::luaEventCallbackRegister); + Lua::registerSharedClass(luaState, "EventCallback", "", EventCallbackFunctions::luaEventCallbackCreate); + Lua::registerMethod(luaState, "EventCallback", "type", EventCallbackFunctions::luaEventCallbackType); + Lua::registerMethod(luaState, "EventCallback", "register", EventCallbackFunctions::luaEventCallbackRegister); } int EventCallbackFunctions::luaEventCallbackCreate(lua_State* luaState) { - const auto &callbackName = getString(luaState, 2); + const auto &callbackName = Lua::getString(luaState, 2); if (callbackName.empty()) { - reportErrorFunc("Invalid callback name"); + Lua::reportErrorFunc("Invalid callback name"); return 1; } - bool skipDuplicationCheck = getBoolean(luaState, 3, false); - const auto eventCallback = std::make_shared<EventCallback>(getScriptEnv()->getScriptInterface(), callbackName, skipDuplicationCheck); - pushUserdata<EventCallback>(luaState, eventCallback); - setMetatable(luaState, -1, "EventCallback"); + bool skipDuplicationCheck = Lua::getBoolean(luaState, 3, false); + const auto eventCallback = std::make_shared<EventCallback>(callbackName, skipDuplicationCheck); + Lua::pushUserdata<EventCallback>(luaState, eventCallback); + Lua::setMetatable(luaState, -1, "EventCallback"); return 1; } int EventCallbackFunctions::luaEventCallbackType(lua_State* luaState) { - auto callback = getUserdataShared<EventCallback>(luaState, 1); + const auto &callback = Lua::getUserdataShared<EventCallback>(luaState, 1); if (!callback) { - reportErrorFunc("EventCallback is nil"); + Lua::reportErrorFunc("EventCallback is nil"); return 0; } - auto typeName = getString(luaState, 2); + auto typeName = Lua::getString(luaState, 2); auto lowerTypeName = asLowerCaseString(typeName); bool found = false; for (auto enumValue : magic_enum::enum_values<EventCallback_t>()) { @@ -69,47 +70,45 @@ int EventCallbackFunctions::luaEventCallbackType(lua_State* luaState) { if (!found) { g_logger().error("[{}] No valid event name: {}", __func__, typeName); - pushBoolean(luaState, false); + Lua::pushBoolean(luaState, false); } - pushBoolean(luaState, true); + Lua::pushBoolean(luaState, true); return 1; } int EventCallbackFunctions::luaEventCallbackRegister(lua_State* luaState) { - auto callback = getUserdataShared<EventCallback>(luaState, 1); + const auto &callback = Lua::getUserdataShared<EventCallback>(luaState, 1); if (!callback) { - reportErrorFunc("EventCallback is nil, failed to register script"); return 0; } - if (!callback->isLoadedCallback()) { + if (!callback->isLoadedScriptId()) { return 0; } if (g_callbacks().isCallbackRegistered(callback)) { - reportErrorFunc(fmt::format("EventCallback is duplicated for event with name: {}", callback->getName())); + Lua::reportErrorFunc(fmt::format("EventCallback is duplicated for event with name: {}", callback->getName())); return 0; } g_callbacks().addCallback(callback); - pushBoolean(luaState, true); + Lua::pushBoolean(luaState, true); return 1; } // Callback functions int EventCallbackFunctions::luaEventCallbackLoad(lua_State* luaState) { - auto callback = getUserdataShared<EventCallback>(luaState, 1); + const auto &callback = Lua::getUserdataShared<EventCallback>(luaState, 1); if (!callback) { return 1; } - if (!callback->loadCallback()) { - reportErrorFunc("Cannot load callback"); + if (!callback->loadScriptId()) { + Lua::reportErrorFunc("Cannot load callback"); return 1; } - callback->setLoadedCallback(true); - pushBoolean(luaState, true); + Lua::pushBoolean(luaState, true); return 1; } diff --git a/src/lua/functions/events/event_callback_functions.hpp b/src/lua/functions/events/event_callback_functions.hpp index a5fa9e8900c..34a08995b2b 100644 --- a/src/lua/functions/events/event_callback_functions.hpp +++ b/src/lua/functions/events/event_callback_functions.hpp @@ -9,8 +9,6 @@ #pragma once -#include "lua/scripts/luascript.hpp" - /** * @class EventCallbackFunctions * @brief Provides a set of static functions for working with Event Callbacks in Lua. @@ -18,7 +16,7 @@ * @details This class encapsulates the Lua binding functions related to event callbacks, * allowing for interaction between the C++ codebase and Lua scripts. */ -class EventCallbackFunctions : public LuaScriptInterface { +class EventCallbackFunctions { public: /** * @brief Initializes the Lua state with the event callback functions. diff --git a/src/lua/functions/events/events_functions.hpp b/src/lua/functions/events/events_functions.hpp index 6830b7c1a73..4a4e3570a12 100644 --- a/src/lua/functions/events/events_functions.hpp +++ b/src/lua/functions/events/events_functions.hpp @@ -20,6 +20,12 @@ class EventFunctions final : LuaScriptInterface { public: + explicit EventFunctions(lua_State* L) : + LuaScriptInterface("EventFunctions") { + init(L); + } + ~EventFunctions() override = default; + static void init(lua_State* L) { ActionFunctions::init(L); CreatureEventFunctions::init(L); @@ -30,6 +36,4 @@ class EventFunctions final : LuaScriptInterface { EventCallbackFunctions::init(L); /* Move, Creature, Talk, Global events goes all here */ } - -private: }; diff --git a/src/lua/functions/events/events_scheduler_functions.cpp b/src/lua/functions/events/events_scheduler_functions.cpp index eb16cf5c340..0c83a862ff4 100644 --- a/src/lua/functions/events/events_scheduler_functions.cpp +++ b/src/lua/functions/events/events_scheduler_functions.cpp @@ -7,9 +7,21 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/scheduling/events_scheduler.hpp" #include "lua/functions/events/events_scheduler_functions.hpp" +#include "game/scheduling/events_scheduler.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void EventsSchedulerFunctions::init(lua_State* L) { + Lua::registerTable(L, "EventsScheduler"); + + Lua::registerMethod(L, "EventsScheduler", "getEventSLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSLoot); + Lua::registerMethod(L, "EventsScheduler", "getEventSBossLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSBossLoot); + Lua::registerMethod(L, "EventsScheduler", "getEventSSkill", EventsSchedulerFunctions::luaEventsSchedulergetEventSSkill); + Lua::registerMethod(L, "EventsScheduler", "getEventSExp", EventsSchedulerFunctions::luaEventsSchedulergetEventSExp); + Lua::registerMethod(L, "EventsScheduler", "getSpawnMonsterSchedule", EventsSchedulerFunctions::luaEventsSchedulergetSpawnMonsterSchedule); +} + int EventsSchedulerFunctions::luaEventsSchedulergetEventSLoot(lua_State* L) { // EventsScheduler.getEventSLoot lua_pushnumber(L, g_eventsScheduler().getLootSchedule()); diff --git a/src/lua/functions/events/events_scheduler_functions.hpp b/src/lua/functions/events/events_scheduler_functions.hpp index bedbf16b4a1..58919ebc9c5 100644 --- a/src/lua/functions/events/events_scheduler_functions.hpp +++ b/src/lua/functions/events/events_scheduler_functions.hpp @@ -9,19 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class EventsSchedulerFunctions final : private LuaScriptInterface { +class EventsSchedulerFunctions { public: - static void init(lua_State* L) { - registerTable(L, "EventsScheduler"); - - registerMethod(L, "EventsScheduler", "getEventSLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSLoot); - registerMethod(L, "EventsScheduler", "getEventSBossLoot", EventsSchedulerFunctions::luaEventsSchedulergetEventSBossLoot); - registerMethod(L, "EventsScheduler", "getEventSSkill", EventsSchedulerFunctions::luaEventsSchedulergetEventSSkill); - registerMethod(L, "EventsScheduler", "getEventSExp", EventsSchedulerFunctions::luaEventsSchedulergetEventSExp); - registerMethod(L, "EventsScheduler", "getSpawnMonsterSchedule", EventsSchedulerFunctions::luaEventsSchedulergetSpawnMonsterSchedule); - } + static void init(lua_State* L); private: static int luaEventsSchedulergetEventSLoot(lua_State* L); diff --git a/src/lua/functions/events/global_event_functions.cpp b/src/lua/functions/events/global_event_functions.cpp index c858ee9a831..b7dddb9bb02 100644 --- a/src/lua/functions/events/global_event_functions.cpp +++ b/src/lua/functions/events/global_event_functions.cpp @@ -8,26 +8,42 @@ */ #include "lua/functions/events/global_event_functions.hpp" + #include "game/game.hpp" #include "lua/global/globalevent.hpp" -#include "lua/scripts/scripts.hpp" #include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void GlobalEventFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "GlobalEvent", "", GlobalEventFunctions::luaCreateGlobalEvent); + Lua::registerMethod(L, "GlobalEvent", "type", GlobalEventFunctions::luaGlobalEventType); + Lua::registerMethod(L, "GlobalEvent", "register", GlobalEventFunctions::luaGlobalEventRegister); + Lua::registerMethod(L, "GlobalEvent", "time", GlobalEventFunctions::luaGlobalEventTime); + Lua::registerMethod(L, "GlobalEvent", "interval", GlobalEventFunctions::luaGlobalEventInterval); + Lua::registerMethod(L, "GlobalEvent", "onThink", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onTime", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onStartup", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onShutdown", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onRecord", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onPeriodChange", GlobalEventFunctions::luaGlobalEventOnCallback); + Lua::registerMethod(L, "GlobalEvent", "onSave", GlobalEventFunctions::luaGlobalEventOnCallback); +} int GlobalEventFunctions::luaCreateGlobalEvent(lua_State* L) { - const auto global = std::make_shared<GlobalEvent>(getScriptEnv()->getScriptInterface()); - global->setName(getString(L, 2)); + const auto global = std::make_shared<GlobalEvent>(); + global->setName(Lua::getString(L, 2)); global->setEventType(GLOBALEVENT_NONE); - pushUserdata<GlobalEvent>(L, global); - setMetatable(L, -1, "GlobalEvent"); + Lua::pushUserdata<GlobalEvent>(L, global); + Lua::setMetatable(L, -1, "GlobalEvent"); return 1; } int GlobalEventFunctions::luaGlobalEventType(lua_State* L) { // globalevent:type(callback) - const auto global = getUserdataShared<GlobalEvent>(L, 1); + const auto &global = Lua::getUserdataShared<GlobalEvent>(L, 1); if (global) { - std::string typeName = getString(L, 2); - std::string tmpStr = asLowerCaseString(typeName); + const std::string typeName = Lua::getString(L, 2); + const std::string tmpStr = asLowerCaseString(typeName); if (tmpStr == "startup") { global->setEventType(GLOBALEVENT_STARTUP); } else if (tmpStr == "shutdown") { @@ -43,9 +59,9 @@ int GlobalEventFunctions::luaGlobalEventType(lua_State* L) { } else { g_logger().error("[GlobalEventFunctions::luaGlobalEventType] - " "Invalid type for global event: {}"); - pushBoolean(L, false); + Lua::pushBoolean(L, false); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -54,18 +70,18 @@ int GlobalEventFunctions::luaGlobalEventType(lua_State* L) { int GlobalEventFunctions::luaGlobalEventRegister(lua_State* L) { // globalevent:register() - const auto globalevent = getUserdataShared<GlobalEvent>(L, 1); + const auto &globalevent = Lua::getUserdataShared<GlobalEvent>(L, 1); if (globalevent) { - if (!globalevent->isLoadedCallback()) { - pushBoolean(L, false); + if (!globalevent->isLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } if (globalevent->getEventType() == GLOBALEVENT_NONE && globalevent->getInterval() == 0) { g_logger().error("{} - No interval for globalevent with name {}", __FUNCTION__, globalevent->getName()); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_globalEvents().registerLuaEvent(globalevent)); + Lua::pushBoolean(L, g_globalEvents().registerLuaEvent(globalevent)); } else { lua_pushnil(L); } @@ -74,13 +90,13 @@ int GlobalEventFunctions::luaGlobalEventRegister(lua_State* L) { int GlobalEventFunctions::luaGlobalEventOnCallback(lua_State* L) { // globalevent:onThink / record / etc. (callback) - const auto globalevent = getUserdataShared<GlobalEvent>(L, 1); + const auto &globalevent = Lua::getUserdataShared<GlobalEvent>(L, 1); if (globalevent) { - if (!globalevent->loadCallback()) { - pushBoolean(L, false); + if (!globalevent->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -89,17 +105,17 @@ int GlobalEventFunctions::luaGlobalEventOnCallback(lua_State* L) { int GlobalEventFunctions::luaGlobalEventTime(lua_State* L) { // globalevent:time(time) - const auto globalevent = getUserdataShared<GlobalEvent>(L, 1); + const auto &globalevent = Lua::getUserdataShared<GlobalEvent>(L, 1); if (globalevent) { - std::string timer = getString(L, 2); - std::vector<int32_t> params = vectorAtoi(explodeString(timer, ":")); + std::string timer = Lua::getString(L, 2); + const std::vector<int32_t> params = vectorAtoi(explodeString(timer, ":")); - int32_t hour = params.front(); + const int32_t hour = params.front(); if (hour < 0 || hour > 23) { g_logger().error("[GlobalEventFunctions::luaGlobalEventTime] - " "Invalid hour {} for globalevent with name: {}", timer, globalevent->getName()); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -113,7 +129,7 @@ int GlobalEventFunctions::luaGlobalEventTime(lua_State* L) { g_logger().error("[GlobalEventFunctions::luaGlobalEventTime] - " "Invalid minute: {} for globalevent with name: {}", timer, globalevent->getName()); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } @@ -123,19 +139,19 @@ int GlobalEventFunctions::luaGlobalEventTime(lua_State* L) { g_logger().error("[GlobalEventFunctions::luaGlobalEventTime] - " "Invalid minute: {} for globalevent with name: {}", timer, globalevent->getName()); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } } } - time_t current_time = time(nullptr); + const time_t current_time = time(nullptr); tm* timeinfo = localtime(¤t_time); timeinfo->tm_hour = hour; timeinfo->tm_min = min; timeinfo->tm_sec = sec; - time_t difference = static_cast<time_t>(difftime(mktime(timeinfo), current_time)); + auto difference = static_cast<time_t>(difftime(mktime(timeinfo), current_time)); // If the difference is negative, add 86400 seconds (1 day) to it if (difference < 0) { difference += 86400; @@ -143,7 +159,7 @@ int GlobalEventFunctions::luaGlobalEventTime(lua_State* L) { globalevent->setNextExecution(current_time + difference); globalevent->setEventType(GLOBALEVENT_TIMER); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -152,11 +168,11 @@ int GlobalEventFunctions::luaGlobalEventTime(lua_State* L) { int GlobalEventFunctions::luaGlobalEventInterval(lua_State* L) { // globalevent:interval(interval) - const auto globalevent = getUserdataShared<GlobalEvent>(L, 1); + const auto &globalevent = Lua::getUserdataShared<GlobalEvent>(L, 1); if (globalevent) { - globalevent->setInterval(getNumber<uint32_t>(L, 2)); - globalevent->setNextExecution(OTSYS_TIME() + getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + globalevent->setInterval(Lua::getNumber<uint32_t>(L, 2)); + globalevent->setNextExecution(OTSYS_TIME() + Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/events/global_event_functions.hpp b/src/lua/functions/events/global_event_functions.hpp index e04072a24e4..1860a7a8d39 100644 --- a/src/lua/functions/events/global_event_functions.hpp +++ b/src/lua/functions/events/global_event_functions.hpp @@ -9,24 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class GlobalEventFunctions final : LuaScriptInterface { +class GlobalEventFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "GlobalEvent", "", GlobalEventFunctions::luaCreateGlobalEvent); - registerMethod(L, "GlobalEvent", "type", GlobalEventFunctions::luaGlobalEventType); - registerMethod(L, "GlobalEvent", "register", GlobalEventFunctions::luaGlobalEventRegister); - registerMethod(L, "GlobalEvent", "time", GlobalEventFunctions::luaGlobalEventTime); - registerMethod(L, "GlobalEvent", "interval", GlobalEventFunctions::luaGlobalEventInterval); - registerMethod(L, "GlobalEvent", "onThink", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onTime", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onStartup", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onShutdown", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onRecord", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onPeriodChange", GlobalEventFunctions::luaGlobalEventOnCallback); - registerMethod(L, "GlobalEvent", "onSave", GlobalEventFunctions::luaGlobalEventOnCallback); - } + static void init(lua_State* L); private: static int luaCreateGlobalEvent(lua_State* L); diff --git a/src/lua/functions/events/move_event_functions.cpp b/src/lua/functions/events/move_event_functions.cpp index cfd8588d19b..c5ea87b5a45 100644 --- a/src/lua/functions/events/move_event_functions.cpp +++ b/src/lua/functions/events/move_event_functions.cpp @@ -7,24 +7,48 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/events/move_event_functions.hpp" + #include "creatures/creature.hpp" #include "lua/creature/movement.hpp" -#include "lua/functions/events/move_event_functions.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void MoveEventFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "MoveEvent", "", MoveEventFunctions::luaCreateMoveEvent); + Lua::registerMethod(L, "MoveEvent", "type", MoveEventFunctions::luaMoveEventType); + Lua::registerMethod(L, "MoveEvent", "register", MoveEventFunctions::luaMoveEventRegister); + Lua::registerMethod(L, "MoveEvent", "level", MoveEventFunctions::luaMoveEventLevel); + Lua::registerMethod(L, "MoveEvent", "magicLevel", MoveEventFunctions::luaMoveEventMagLevel); + Lua::registerMethod(L, "MoveEvent", "slot", MoveEventFunctions::luaMoveEventSlot); + Lua::registerMethod(L, "MoveEvent", "id", MoveEventFunctions::luaMoveEventItemId); + Lua::registerMethod(L, "MoveEvent", "aid", MoveEventFunctions::luaMoveEventActionId); + Lua::registerMethod(L, "MoveEvent", "uid", MoveEventFunctions::luaMoveEventUniqueId); + Lua::registerMethod(L, "MoveEvent", "position", MoveEventFunctions::luaMoveEventPosition); + Lua::registerMethod(L, "MoveEvent", "premium", MoveEventFunctions::luaMoveEventPremium); + Lua::registerMethod(L, "MoveEvent", "vocation", MoveEventFunctions::luaMoveEventVocation); + Lua::registerMethod(L, "MoveEvent", "onEquip", MoveEventFunctions::luaMoveEventOnCallback); + Lua::registerMethod(L, "MoveEvent", "onDeEquip", MoveEventFunctions::luaMoveEventOnCallback); + Lua::registerMethod(L, "MoveEvent", "onStepIn", MoveEventFunctions::luaMoveEventOnCallback); + Lua::registerMethod(L, "MoveEvent", "onStepOut", MoveEventFunctions::luaMoveEventOnCallback); + Lua::registerMethod(L, "MoveEvent", "onAddItem", MoveEventFunctions::luaMoveEventOnCallback); + Lua::registerMethod(L, "MoveEvent", "onRemoveItem", MoveEventFunctions::luaMoveEventOnCallback); +} int MoveEventFunctions::luaCreateMoveEvent(lua_State* L) { // MoveEvent() - const auto moveevent = std::make_shared<MoveEvent>(getScriptEnv()->getScriptInterface()); - pushUserdata<MoveEvent>(L, moveevent); - setMetatable(L, -1, "MoveEvent"); + const auto moveevent = std::make_shared<MoveEvent>(); + Lua::pushUserdata<MoveEvent>(L, moveevent); + Lua::setMetatable(L, -1, "MoveEvent"); return 1; } int MoveEventFunctions::luaMoveEventType(lua_State* L) { // moveevent:type(callback) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - std::string typeName = getString(L, 2); - std::string tmpStr = asLowerCaseString(typeName); + std::string typeName = Lua::getString(L, 2); + const std::string tmpStr = asLowerCaseString(typeName); if (tmpStr == "stepin") { moveevent->setEventType(MOVE_EVENT_STEP_IN); moveevent->stepFunction = moveevent->StepInField; @@ -47,9 +71,9 @@ int MoveEventFunctions::luaMoveEventType(lua_State* L) { g_logger().error("[MoveEventFunctions::luaMoveEventType] - " "No valid event name: {}", typeName); - pushBoolean(L, false); + Lua::pushBoolean(L, false); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -58,16 +82,16 @@ int MoveEventFunctions::luaMoveEventType(lua_State* L) { int MoveEventFunctions::luaMoveEventRegister(lua_State* L) { // moveevent:register() - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { // If not scripted, register item event // Example: unscripted_equipments.lua - if (!moveevent->isLoadedCallback()) { - pushBoolean(L, g_moveEvents().registerLuaItemEvent(moveevent)); + if (!moveevent->isLoadedScriptId()) { + Lua::pushBoolean(L, g_moveEvents().registerLuaItemEvent(moveevent)); return 1; } - pushBoolean(L, g_moveEvents().registerLuaEvent(moveevent)); + Lua::pushBoolean(L, g_moveEvents().registerLuaEvent(moveevent)); } else { lua_pushnil(L); } @@ -76,14 +100,14 @@ int MoveEventFunctions::luaMoveEventRegister(lua_State* L) { int MoveEventFunctions::luaMoveEventOnCallback(lua_State* L) { // moveevent:onEquip / deEquip / etc. (callback) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - if (!moveevent->loadCallback()) { - pushBoolean(L, false); + if (!moveevent->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -92,14 +116,14 @@ int MoveEventFunctions::luaMoveEventOnCallback(lua_State* L) { int MoveEventFunctions::luaMoveEventSlot(lua_State* L) { // moveevent:slot(slot) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (!moveevent) { lua_pushnil(L); return 1; } if (moveevent->getEventType() == MOVE_EVENT_EQUIP || moveevent->getEventType() == MOVE_EVENT_DEEQUIP) { - std::string slotName = asLowerCaseString(getString(L, 2)); + std::string slotName = asLowerCaseString(Lua::getString(L, 2)); if (slotName == "head") { moveevent->setSlot(SLOTP_HEAD); } else if (slotName == "necklace") { @@ -126,22 +150,22 @@ int MoveEventFunctions::luaMoveEventSlot(lua_State* L) { g_logger().warn("[MoveEventFunctions::luaMoveEventSlot] - " "Unknown slot type: {}", slotName); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int MoveEventFunctions::luaMoveEventLevel(lua_State* L) { // moveevent:level(lvl) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - moveevent->setRequiredLevel(getNumber<uint32_t>(L, 2)); + moveevent->setRequiredLevel(Lua::getNumber<uint32_t>(L, 2)); moveevent->setWieldInfo(WIELDINFO_LEVEL); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -150,11 +174,11 @@ int MoveEventFunctions::luaMoveEventLevel(lua_State* L) { int MoveEventFunctions::luaMoveEventMagLevel(lua_State* L) { // moveevent:magicLevel(lvl) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - moveevent->setRequiredMagLevel(getNumber<uint32_t>(L, 2)); + moveevent->setRequiredMagLevel(Lua::getNumber<uint32_t>(L, 2)); moveevent->setWieldInfo(WIELDINFO_MAGLV); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -163,11 +187,11 @@ int MoveEventFunctions::luaMoveEventMagLevel(lua_State* L) { int MoveEventFunctions::luaMoveEventPremium(lua_State* L) { // moveevent:premium(bool) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - moveevent->setNeedPremium(getBoolean(L, 2)); + moveevent->setNeedPremium(Lua::getBoolean(L, 2)); moveevent->setWieldInfo(WIELDINFO_PREMIUM); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -176,22 +200,22 @@ int MoveEventFunctions::luaMoveEventPremium(lua_State* L) { int MoveEventFunctions::luaMoveEventVocation(lua_State* L) { // moveevent:vocation(vocName[, showInDescription = false, lastVoc = false]) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - moveevent->addVocEquipMap(getString(L, 2)); + moveevent->addVocEquipMap(Lua::getString(L, 2)); moveevent->setWieldInfo(WIELDINFO_VOCREQ); std::string tmp; bool showInDescription = false; bool lastVoc = false; - if (getBoolean(L, 3)) { - showInDescription = getBoolean(L, 3); + if (Lua::getBoolean(L, 3)) { + showInDescription = Lua::getBoolean(L, 3); } - if (getBoolean(L, 4)) { - lastVoc = getBoolean(L, 4); + if (Lua::getBoolean(L, 4)) { + lastVoc = Lua::getBoolean(L, 4); } if (showInDescription) { if (moveevent->getVocationString().empty()) { - tmp = asLowerCaseString(getString(L, 2)); + tmp = asLowerCaseString(Lua::getString(L, 2)); tmp += "s"; moveevent->setVocationString(tmp); } else { @@ -201,12 +225,12 @@ int MoveEventFunctions::luaMoveEventVocation(lua_State* L) { } else { tmp += ", "; } - tmp += asLowerCaseString(getString(L, 2)); + tmp += asLowerCaseString(Lua::getString(L, 2)); tmp += "s"; moveevent->setVocationString(tmp); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -215,17 +239,17 @@ int MoveEventFunctions::luaMoveEventVocation(lua_State* L) { int MoveEventFunctions::luaMoveEventItemId(lua_State* L) { // moveevent:id(ids) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - moveevent->setItemId(getNumber<uint32_t>(L, 2 + i)); + moveevent->setItemId(Lua::getNumber<uint32_t>(L, 2 + i)); } } else { - moveevent->setItemId(getNumber<uint32_t>(L, 2)); + moveevent->setItemId(Lua::getNumber<uint32_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -234,17 +258,17 @@ int MoveEventFunctions::luaMoveEventItemId(lua_State* L) { int MoveEventFunctions::luaMoveEventActionId(lua_State* L) { // moveevent:aid(ids) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - moveevent->setActionId(getNumber<uint32_t>(L, 2 + i)); + moveevent->setActionId(Lua::getNumber<uint32_t>(L, 2 + i)); } } else { - moveevent->setActionId(getNumber<uint32_t>(L, 2)); + moveevent->setActionId(Lua::getNumber<uint32_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -253,17 +277,17 @@ int MoveEventFunctions::luaMoveEventActionId(lua_State* L) { int MoveEventFunctions::luaMoveEventUniqueId(lua_State* L) { // moveevent:uid(ids) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - moveevent->setUniqueId(getNumber<uint32_t>(L, 2 + i)); + moveevent->setUniqueId(Lua::getNumber<uint32_t>(L, 2 + i)); } } else { - moveevent->setUniqueId(getNumber<uint32_t>(L, 2)); + moveevent->setUniqueId(Lua::getNumber<uint32_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -272,17 +296,17 @@ int MoveEventFunctions::luaMoveEventUniqueId(lua_State* L) { int MoveEventFunctions::luaMoveEventPosition(lua_State* L) { // moveevent:position(positions) - const auto moveevent = getUserdataShared<MoveEvent>(L, 1); + const auto &moveevent = Lua::getUserdataShared<MoveEvent>(L, 1); if (moveevent) { - int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc + const int parameters = lua_gettop(L) - 1; // - 1 because self is a parameter aswell, which we want to skip ofc if (parameters > 1) { for (int i = 0; i < parameters; ++i) { - moveevent->setPosition(getPosition(L, 2 + i)); + moveevent->setPosition(Lua::getPosition(L, 2 + i)); } } else { - moveevent->setPosition(getPosition(L, 2)); + moveevent->setPosition(Lua::getPosition(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/events/move_event_functions.hpp b/src/lua/functions/events/move_event_functions.hpp index 6e6412bec73..cfc30c3ecda 100644 --- a/src/lua/functions/events/move_event_functions.hpp +++ b/src/lua/functions/events/move_event_functions.hpp @@ -9,30 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class MoveEventFunctions final : LuaScriptInterface { +class MoveEventFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "MoveEvent", "", MoveEventFunctions::luaCreateMoveEvent); - registerMethod(L, "MoveEvent", "type", MoveEventFunctions::luaMoveEventType); - registerMethod(L, "MoveEvent", "register", MoveEventFunctions::luaMoveEventRegister); - registerMethod(L, "MoveEvent", "level", MoveEventFunctions::luaMoveEventLevel); - registerMethod(L, "MoveEvent", "magicLevel", MoveEventFunctions::luaMoveEventMagLevel); - registerMethod(L, "MoveEvent", "slot", MoveEventFunctions::luaMoveEventSlot); - registerMethod(L, "MoveEvent", "id", MoveEventFunctions::luaMoveEventItemId); - registerMethod(L, "MoveEvent", "aid", MoveEventFunctions::luaMoveEventActionId); - registerMethod(L, "MoveEvent", "uid", MoveEventFunctions::luaMoveEventUniqueId); - registerMethod(L, "MoveEvent", "position", MoveEventFunctions::luaMoveEventPosition); - registerMethod(L, "MoveEvent", "premium", MoveEventFunctions::luaMoveEventPremium); - registerMethod(L, "MoveEvent", "vocation", MoveEventFunctions::luaMoveEventVocation); - registerMethod(L, "MoveEvent", "onEquip", MoveEventFunctions::luaMoveEventOnCallback); - registerMethod(L, "MoveEvent", "onDeEquip", MoveEventFunctions::luaMoveEventOnCallback); - registerMethod(L, "MoveEvent", "onStepIn", MoveEventFunctions::luaMoveEventOnCallback); - registerMethod(L, "MoveEvent", "onStepOut", MoveEventFunctions::luaMoveEventOnCallback); - registerMethod(L, "MoveEvent", "onAddItem", MoveEventFunctions::luaMoveEventOnCallback); - registerMethod(L, "MoveEvent", "onRemoveItem", MoveEventFunctions::luaMoveEventOnCallback); - } + static void init(lua_State* L); private: static int luaCreateMoveEvent(lua_State* L); diff --git a/src/lua/functions/events/talk_action_functions.cpp b/src/lua/functions/events/talk_action_functions.cpp index 4a8e9850d7f..39328ea7de4 100644 --- a/src/lua/functions/events/talk_action_functions.cpp +++ b/src/lua/functions/events/talk_action_functions.cpp @@ -7,59 +7,74 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/events/talk_action_functions.hpp" + #include "account/account.hpp" #include "lua/creature/talkaction.hpp" -#include "lua/functions/events/talk_action_functions.hpp" #include "utils/tools.hpp" #include "enums/account_group_type.hpp" +#include "lua/functions/lua_functions_loader.hpp" +#include "lua/scripts/luascript.hpp" + +void TalkActionFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "TalkAction", "", TalkActionFunctions::luaCreateTalkAction); + Lua::registerMethod(L, "TalkAction", "onSay", TalkActionFunctions::luaTalkActionOnSay); + Lua::registerMethod(L, "TalkAction", "groupType", TalkActionFunctions::luaTalkActionGroupType); + Lua::registerMethod(L, "TalkAction", "register", TalkActionFunctions::luaTalkActionRegister); + Lua::registerMethod(L, "TalkAction", "separator", TalkActionFunctions::luaTalkActionSeparator); + Lua::registerMethod(L, "TalkAction", "getName", TalkActionFunctions::luaTalkActionGetName); + Lua::registerMethod(L, "TalkAction", "getDescription", TalkActionFunctions::luaTalkActionGetDescription); + Lua::registerMethod(L, "TalkAction", "setDescription", TalkActionFunctions::luaTalkActionSetDescription); + Lua::registerMethod(L, "TalkAction", "getGroupType", TalkActionFunctions::luaTalkActionGetGroupType); +} int TalkActionFunctions::luaCreateTalkAction(lua_State* L) { // TalkAction(words) or TalkAction(word1, word2, word3) std::vector<std::string> wordsVector; for (int i = 2; i <= lua_gettop(L); i++) { - wordsVector.push_back(getString(L, i)); + wordsVector.push_back(Lua::getString(L, i)); } - auto talkactionSharedPtr = std::make_shared<TalkAction>(getScriptEnv()->getScriptInterface()); + const auto talkactionSharedPtr = std::make_shared<TalkAction>(); talkactionSharedPtr->setWords(wordsVector); - pushUserdata<TalkAction>(L, talkactionSharedPtr); - setMetatable(L, -1, "TalkAction"); + Lua::pushUserdata<TalkAction>(L, talkactionSharedPtr); + Lua::setMetatable(L, -1, "TalkAction"); return 1; } int TalkActionFunctions::luaTalkActionOnSay(lua_State* L) { // talkAction:onSay(callback) - auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - if (!talkactionSharedPtr->loadCallback()) { - pushBoolean(L, false); + if (!talkactionSharedPtr->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int TalkActionFunctions::luaTalkActionGroupType(lua_State* L) { // talkAction:groupType(GroupType = GROUP_TYPE_NORMAL) - auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } GroupType groupType; - int type = lua_type(L, 2); + const int type = lua_type(L, 2); if (type == LUA_TNUMBER) { - groupType = enumFromValue<GroupType>(getNumber<uint8_t>(L, 2)); + groupType = enumFromValue<GroupType>(Lua::getNumber<uint8_t>(L, 2)); } else if (type == LUA_TSTRING) { - std::string strValue = getString(L, 2); + std::string strValue = Lua::getString(L, 2); if (strValue == "normal") { groupType = GROUP_TYPE_NORMAL; } else if (strValue == "tutor") { @@ -73,108 +88,108 @@ int TalkActionFunctions::luaTalkActionGroupType(lua_State* L) { } else if (strValue == "god") { groupType = GROUP_TYPE_GOD; } else { - auto string = fmt::format("Invalid group type string value {} for group type for script: {}", strValue, getScriptEnv()->getScriptInterface()->getLoadingScriptName()); - reportErrorFunc(string); - pushBoolean(L, false); + const auto string = fmt::format("Invalid group type string value {} for group type for script: {}", strValue, Lua::getScriptEnv()->getScriptInterface()->getLoadingScriptName()); + Lua::reportErrorFunc(string); + Lua::pushBoolean(L, false); return 1; } } else { - auto string = fmt::format("Expected number or string value for group type for script: {}", getScriptEnv()->getScriptInterface()->getLoadingScriptName()); - reportErrorFunc(string); - pushBoolean(L, false); + const auto string = fmt::format("Expected number or string value for group type for script: {}", Lua::getScriptEnv()->getScriptInterface()->getLoadingScriptName()); + Lua::reportErrorFunc(string); + Lua::pushBoolean(L, false); return 1; } talkactionSharedPtr->setGroupType(groupType); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int TalkActionFunctions::luaTalkActionRegister(lua_State* L) { // talkAction:register() - auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - if (!talkactionSharedPtr->isLoadedCallback()) { - pushBoolean(L, false); + if (!talkactionSharedPtr->isLoadedScriptId()) { + Lua::pushBoolean(L, false); return 1; } if (talkactionSharedPtr->getGroupType() == GROUP_TYPE_NONE) { - auto string = fmt::format("TalkAction with name {} does't have groupType", talkactionSharedPtr->getWords()); - reportErrorFunc(string); - pushBoolean(L, false); + const auto string = fmt::format("TalkAction with name {} does't have groupType", talkactionSharedPtr->getWords()); + Lua::reportErrorFunc(string); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, g_talkActions().registerLuaEvent(talkactionSharedPtr)); + Lua::pushBoolean(L, g_talkActions().registerLuaEvent(talkactionSharedPtr)); return 1; } int TalkActionFunctions::luaTalkActionSeparator(lua_State* L) { // talkAction:separator(sep) - auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - talkactionSharedPtr->setSeparator(getString(L, 2)); - pushBoolean(L, true); + talkactionSharedPtr->setSeparator(Lua::getString(L, 2)); + Lua::pushBoolean(L, true); return 1; } int TalkActionFunctions::luaTalkActionGetName(lua_State* L) { // local name = talkAction:getName() - const auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushString(L, talkactionSharedPtr->getWords()); + Lua::pushString(L, talkactionSharedPtr->getWords()); return 1; } int TalkActionFunctions::luaTalkActionGetDescription(lua_State* L) { // local description = talkAction:getDescription() - const auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushString(L, talkactionSharedPtr->getDescription()); + Lua::pushString(L, talkactionSharedPtr->getDescription()); return 1; } int TalkActionFunctions::luaTalkActionSetDescription(lua_State* L) { // local description = talkAction:setDescription() - auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - talkactionSharedPtr->setDescription(getString(L, 2)); - pushBoolean(L, true); + talkactionSharedPtr->setDescription(Lua::getString(L, 2)); + Lua::pushBoolean(L, true); return 1; } int TalkActionFunctions::luaTalkActionGetGroupType(lua_State* L) { // local groupType = talkAction:getGroupType() - const auto talkactionSharedPtr = getUserdataShared<TalkAction>(L, 1); + const auto &talkactionSharedPtr = Lua::getUserdataShared<TalkAction>(L, 1); if (!talkactionSharedPtr) { - reportErrorFunc(getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_TALK_ACTION_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } diff --git a/src/lua/functions/events/talk_action_functions.hpp b/src/lua/functions/events/talk_action_functions.hpp index 384688b4722..5877293bb9e 100644 --- a/src/lua/functions/events/talk_action_functions.hpp +++ b/src/lua/functions/events/talk_action_functions.hpp @@ -9,21 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class TalkActionFunctions final : LuaScriptInterface { +class TalkActionFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "TalkAction", "", TalkActionFunctions::luaCreateTalkAction); - registerMethod(L, "TalkAction", "onSay", TalkActionFunctions::luaTalkActionOnSay); - registerMethod(L, "TalkAction", "groupType", TalkActionFunctions::luaTalkActionGroupType); - registerMethod(L, "TalkAction", "register", TalkActionFunctions::luaTalkActionRegister); - registerMethod(L, "TalkAction", "separator", TalkActionFunctions::luaTalkActionSeparator); - registerMethod(L, "TalkAction", "getName", TalkActionFunctions::luaTalkActionGetName); - registerMethod(L, "TalkAction", "getDescription", TalkActionFunctions::luaTalkActionGetDescription); - registerMethod(L, "TalkAction", "setDescription", TalkActionFunctions::luaTalkActionSetDescription); - registerMethod(L, "TalkAction", "getGroupType", TalkActionFunctions::luaTalkActionGetGroupType); - } + static void init(lua_State* L); private: static int luaCreateTalkAction(lua_State* L); diff --git a/src/lua/functions/items/container_functions.cpp b/src/lua/functions/items/container_functions.cpp index 7cc06745b18..934c8ce3ff8 100644 --- a/src/lua/functions/items/container_functions.cpp +++ b/src/lua/functions/items/container_functions.cpp @@ -7,18 +7,42 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/items/container_functions.hpp" + #include "game/game.hpp" #include "items/item.hpp" -#include "lua/functions/items/container_functions.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ContainerFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Container", "Item", ContainerFunctions::luaContainerCreate); + Lua::registerMetaMethod(L, "Container", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Container", "getSize", ContainerFunctions::luaContainerGetSize); + Lua::registerMethod(L, "Container", "getMaxCapacity", ContainerFunctions::luaContainerGetMaxCapacity); + Lua::registerMethod(L, "Container", "getCapacity", ContainerFunctions::luaContainerGetCapacity); + Lua::registerMethod(L, "Container", "getEmptySlots", ContainerFunctions::luaContainerGetEmptySlots); + Lua::registerMethod(L, "Container", "getContentDescription", ContainerFunctions::luaContainerGetContentDescription); + Lua::registerMethod(L, "Container", "getItems", ContainerFunctions::luaContainerGetItems); + Lua::registerMethod(L, "Container", "getItemHoldingCount", ContainerFunctions::luaContainerGetItemHoldingCount); + Lua::registerMethod(L, "Container", "getItemCountById", ContainerFunctions::luaContainerGetItemCountById); + + Lua::registerMethod(L, "Container", "getItem", ContainerFunctions::luaContainerGetItem); + Lua::registerMethod(L, "Container", "hasItem", ContainerFunctions::luaContainerHasItem); + Lua::registerMethod(L, "Container", "addItem", ContainerFunctions::luaContainerAddItem); + Lua::registerMethod(L, "Container", "addItemEx", ContainerFunctions::luaContainerAddItemEx); + Lua::registerMethod(L, "Container", "getCorpseOwner", ContainerFunctions::luaContainerGetCorpseOwner); + Lua::registerMethod(L, "Container", "registerReward", ContainerFunctions::luaContainerRegisterReward); +} int ContainerFunctions::luaContainerCreate(lua_State* L) { // Container(uid) - uint32_t id = getNumber<uint32_t>(L, 2); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); - std::shared_ptr<Container> container = getScriptEnv()->getContainerByUID(id); + const auto &container = Lua::getScriptEnv()->getContainerByUID(id); if (container) { - pushUserdata(L, container); - setMetatable(L, -1, "Container"); + Lua::pushUserdata(L, container); + Lua::setMetatable(L, -1, "Container"); } else { lua_pushnil(L); } @@ -27,7 +51,7 @@ int ContainerFunctions::luaContainerCreate(lua_State* L) { int ContainerFunctions::luaContainerGetSize(lua_State* L) { // container:getSize() - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { lua_pushnumber(L, container->size()); } else { @@ -38,7 +62,7 @@ int ContainerFunctions::luaContainerGetSize(lua_State* L) { int ContainerFunctions::luaContainerGetMaxCapacity(lua_State* L) { // container:getMaxCapacity() - const auto &container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { lua_pushnumber(L, container->getMaxCapacity()); } else { @@ -49,7 +73,7 @@ int ContainerFunctions::luaContainerGetMaxCapacity(lua_State* L) { int ContainerFunctions::luaContainerGetCapacity(lua_State* L) { // container:getCapacity() - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { lua_pushnumber(L, container->capacity()); } else { @@ -60,17 +84,17 @@ int ContainerFunctions::luaContainerGetCapacity(lua_State* L) { int ContainerFunctions::luaContainerGetEmptySlots(lua_State* L) { // container:getEmptySlots([recursive = false]) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } uint32_t slots = container->capacity() - container->size(); - bool recursive = getBoolean(L, 2, false); + const bool recursive = Lua::getBoolean(L, 2, false); if (recursive) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - if (std::shared_ptr<Container> tmpContainer = (*it)->getContainer()) { + if (const auto &tmpContainer = (*it)->getContainer()) { slots += tmpContainer->capacity() - tmpContainer->size(); } } @@ -81,7 +105,7 @@ int ContainerFunctions::luaContainerGetEmptySlots(lua_State* L) { int ContainerFunctions::luaContainerGetItemHoldingCount(lua_State* L) { // container:getItemHoldingCount() - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { lua_pushnumber(L, container->getItemHoldingCount()); } else { @@ -92,17 +116,17 @@ int ContainerFunctions::luaContainerGetItemHoldingCount(lua_State* L) { int ContainerFunctions::luaContainerGetItem(lua_State* L) { // container:getItem(index) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } - uint32_t index = getNumber<uint32_t>(L, 2); - std::shared_ptr<Item> item = container->getItemByIndex(index); + const uint32_t index = Lua::getNumber<uint32_t>(L, 2); + const auto &item = container->getItemByIndex(index); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -111,10 +135,10 @@ int ContainerFunctions::luaContainerGetItem(lua_State* L) { int ContainerFunctions::luaContainerHasItem(lua_State* L) { // container:hasItem(item) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 2); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { - pushBoolean(L, container->isHoldingItem(item)); + Lua::pushBoolean(L, container->isHoldingItem(item)); } else { lua_pushnil(L); } @@ -123,74 +147,74 @@ int ContainerFunctions::luaContainerHasItem(lua_State* L) { int ContainerFunctions::luaContainerAddItem(lua_State* L) { // container:addItem(itemId[, count/subType = 1[, index = INDEX_WHEREEVER[, flags = 0]]]) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); - reportErrorFunc("Container is nullptr"); + Lua::reportErrorFunc("Container is nullptr"); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); - reportErrorFunc("Item id is wrong"); + Lua::reportErrorFunc("Item id is wrong"); return 1; } } - uint32_t count = getNumber<uint32_t>(L, 3, 1); + auto count = Lua::getNumber<uint32_t>(L, 3, 1); const ItemType &it = Item::items[itemId]; if (it.stackable) { count = std::min<uint16_t>(count, it.stackSize); } - std::shared_ptr<Item> item = Item::CreateItem(itemId, count); + const auto &item = Item::CreateItem(itemId, count); if (!item) { lua_pushnil(L); - reportErrorFunc("Item is nullptr"); + Lua::reportErrorFunc("Item is nullptr"); return 1; } - int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER); - uint32_t flags = getNumber<uint32_t>(L, 5, 0); + const auto index = Lua::getNumber<int32_t>(L, 4, INDEX_WHEREEVER); + const auto flags = Lua::getNumber<uint32_t>(L, 5, 0); ReturnValue ret = g_game().internalAddItem(container, item, index, flags); if (ret == RETURNVALUE_NOERROR) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { - reportErrorFunc(fmt::format("Cannot add item to container, error code: '{}'", getReturnMessage(ret))); - pushBoolean(L, false); + Lua::reportErrorFunc(fmt::format("Cannot add item to container, error code: '{}'", getReturnMessage(ret))); + Lua::pushBoolean(L, false); } return 1; } int ContainerFunctions::luaContainerAddItemEx(lua_State* L) { // container:addItemEx(item[, index = INDEX_WHEREEVER[, flags = 0]]) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); + Lua::reportErrorFunc("Item already has a parent"); lua_pushnil(L); return 1; } - int32_t index = getNumber<int32_t>(L, 3, INDEX_WHEREEVER); - uint32_t flags = getNumber<uint32_t>(L, 4, 0); + const auto index = Lua::getNumber<int32_t>(L, 3, INDEX_WHEREEVER); + const auto flags = Lua::getNumber<uint32_t>(L, 4, 0); ReturnValue ret = g_game().internalAddItem(container, item, index, flags); if (ret == RETURNVALUE_NOERROR) { ScriptEnvironment::removeTempItem(item); @@ -201,7 +225,7 @@ int ContainerFunctions::luaContainerAddItemEx(lua_State* L) { int ContainerFunctions::luaContainerGetCorpseOwner(lua_State* L) { // container:getCorpseOwner() - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { lua_pushnumber(L, container->getCorpseOwner()); } else { @@ -212,33 +236,33 @@ int ContainerFunctions::luaContainerGetCorpseOwner(lua_State* L) { int ContainerFunctions::luaContainerGetItemCountById(lua_State* L) { // container:getItemCountById(itemId[, subType = -1]) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t subType = getNumber<int32_t>(L, 3, -1); + const auto subType = Lua::getNumber<int32_t>(L, 3, -1); lua_pushnumber(L, container->getItemTypeCount(itemId, subType)); return 1; } int ContainerFunctions::luaContainerGetContentDescription(lua_State* L) { // container:getContentDescription([oldProtocol]) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (container) { - pushString(L, container->getContentDescription(getBoolean(L, 2, false))); + Lua::pushString(L, container->getContentDescription(Lua::getBoolean(L, 2, false))); } else { lua_pushnil(L); } @@ -247,22 +271,22 @@ int ContainerFunctions::luaContainerGetContentDescription(lua_State* L) { int ContainerFunctions::luaContainerGetItems(lua_State* L) { // container:getItems([recursive = false]) - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } - bool recursive = getBoolean(L, 2, false); - std::vector<std::shared_ptr<Item>> items = container->getItems(recursive); + const bool recursive = Lua::getBoolean(L, 2, false); + const std::vector<std::shared_ptr<Item>> items = container->getItems(recursive); lua_createtable(L, static_cast<int>(items.size()), 0); int index = 0; - for (std::shared_ptr<Item> item : items) { + for (const auto &item : items) { index++; - pushUserdata(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata(L, item); + Lua::setItemMetatable(L, -1, item); lua_rawseti(L, -2, index); } return 1; @@ -270,19 +294,19 @@ int ContainerFunctions::luaContainerGetItems(lua_State* L) { int ContainerFunctions::luaContainerRegisterReward(lua_State* L) { // container:registerReward() - std::shared_ptr<Container> container = getUserdataShared<Container>(L, 1); + const auto &container = Lua::getUserdataShared<Container>(L, 1); if (!container) { lua_pushnil(L); return 1; } - int64_t rewardId = getTimeMsNow(); - std::shared_ptr<Item> rewardContainer = Item::CreateItem(ITEM_REWARD_CONTAINER); + const int64_t rewardId = getTimeMsNow(); + const auto &rewardContainer = Item::CreateItem(ITEM_REWARD_CONTAINER); rewardContainer->setAttribute(ItemAttribute_t::DATE, rewardId); container->setAttribute(ItemAttribute_t::DATE, rewardId); container->internalAddThing(rewardContainer); container->setRewardCorpse(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/items/container_functions.hpp b/src/lua/functions/items/container_functions.hpp index 568018b45fd..8510a717b48 100644 --- a/src/lua/functions/items/container_functions.hpp +++ b/src/lua/functions/items/container_functions.hpp @@ -9,31 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ContainerFunctions final : LuaScriptInterface { -public: +class ContainerFunctions { private: - static void init(lua_State* L) { - registerSharedClass(L, "Container", "Item", ContainerFunctions::luaContainerCreate); - registerMetaMethod(L, "Container", "__eq", ContainerFunctions::luaUserdataCompare); - - registerMethod(L, "Container", "getSize", ContainerFunctions::luaContainerGetSize); - registerMethod(L, "Container", "getMaxCapacity", ContainerFunctions::luaContainerGetMaxCapacity); - registerMethod(L, "Container", "getCapacity", ContainerFunctions::luaContainerGetCapacity); - registerMethod(L, "Container", "getEmptySlots", ContainerFunctions::luaContainerGetEmptySlots); - registerMethod(L, "Container", "getContentDescription", ContainerFunctions::luaContainerGetContentDescription); - registerMethod(L, "Container", "getItems", ContainerFunctions::luaContainerGetItems); - registerMethod(L, "Container", "getItemHoldingCount", ContainerFunctions::luaContainerGetItemHoldingCount); - registerMethod(L, "Container", "getItemCountById", ContainerFunctions::luaContainerGetItemCountById); - - registerMethod(L, "Container", "getItem", ContainerFunctions::luaContainerGetItem); - registerMethod(L, "Container", "hasItem", ContainerFunctions::luaContainerHasItem); - registerMethod(L, "Container", "addItem", ContainerFunctions::luaContainerAddItem); - registerMethod(L, "Container", "addItemEx", ContainerFunctions::luaContainerAddItemEx); - registerMethod(L, "Container", "getCorpseOwner", ContainerFunctions::luaContainerGetCorpseOwner); - registerMethod(L, "Container", "registerReward", ContainerFunctions::luaContainerRegisterReward); - } + static void init(lua_State* L); static int luaContainerCreate(lua_State* L); diff --git a/src/lua/functions/items/imbuement_functions.cpp b/src/lua/functions/items/imbuement_functions.cpp index 1faed911621..b28cc771a78 100644 --- a/src/lua/functions/items/imbuement_functions.cpp +++ b/src/lua/functions/items/imbuement_functions.cpp @@ -7,18 +7,34 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/items/imbuement_functions.hpp" + #include "items/weapons/weapons.hpp" #include "creatures/players/imbuements/imbuements.hpp" -#include "lua/functions/items/imbuement_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ImbuementFunctions::init(lua_State* L) { + Lua::registerClass(L, "Imbuement", "", ImbuementFunctions::luaCreateImbuement); + Lua::registerMetaMethod(L, "Imbuement", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Imbuement", "getName", ImbuementFunctions::luaImbuementGetName); + Lua::registerMethod(L, "Imbuement", "getId", ImbuementFunctions::luaImbuementGetId); + Lua::registerMethod(L, "Imbuement", "getItems", ImbuementFunctions::luaImbuementGetItems); + Lua::registerMethod(L, "Imbuement", "getBase", ImbuementFunctions::luaImbuementGetBase); + Lua::registerMethod(L, "Imbuement", "getCategory", ImbuementFunctions::luaImbuementGetCategory); + Lua::registerMethod(L, "Imbuement", "isPremium", ImbuementFunctions::luaImbuementIsPremium); + Lua::registerMethod(L, "Imbuement", "getElementDamage", ImbuementFunctions::luaImbuementGetElementDamage); + Lua::registerMethod(L, "Imbuement", "getCombatType", ImbuementFunctions::luaImbuementGetCombatType); +} int ImbuementFunctions::luaCreateImbuement(lua_State* L) { // Imbuement(id) - uint16_t imbuementId = getNumber<uint16_t>(L, 2); + const uint16_t imbuementId = Lua::getNumber<uint16_t>(L, 2); Imbuement* imbuement = g_imbuements().getImbuement(imbuementId); if (imbuement) { - pushUserdata<Imbuement>(L, imbuement); - setMetatable(L, -1, "Imbuement"); + Lua::pushUserdata<Imbuement>(L, imbuement); + Lua::setMetatable(L, -1, "Imbuement"); } else { lua_pushnil(L); } @@ -27,9 +43,9 @@ int ImbuementFunctions::luaCreateImbuement(lua_State* L) { int ImbuementFunctions::luaImbuementGetName(lua_State* L) { // imbuement:getName() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (imbuement) { - pushString(L, imbuement->getName()); + Lua::pushString(L, imbuement->getName()); } else { lua_pushnil(L); } @@ -38,7 +54,7 @@ int ImbuementFunctions::luaImbuementGetName(lua_State* L) { int ImbuementFunctions::luaImbuementGetId(lua_State* L) { // imbuement:getId() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (imbuement) { lua_pushnumber(L, imbuement->getID()); } else { @@ -49,7 +65,7 @@ int ImbuementFunctions::luaImbuementGetId(lua_State* L) { int ImbuementFunctions::luaImbuementGetItems(lua_State* L) { // imbuement:getItems() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (!imbuement) { lua_pushnil(L); return 1; @@ -60,8 +76,8 @@ int ImbuementFunctions::luaImbuementGetItems(lua_State* L) { lua_createtable(L, items.size(), 0); for (const auto &itm : items) { lua_createtable(L, 0, 2); - setField(L, "itemid", itm.first); - setField(L, "count", itm.second); + Lua::setField(L, "itemid", itm.first); + Lua::setField(L, "count", itm.second); lua_rawseti(L, -2, itm.first); } @@ -70,7 +86,7 @@ int ImbuementFunctions::luaImbuementGetItems(lua_State* L) { int ImbuementFunctions::luaImbuementGetBase(lua_State* L) { // imbuement:getBase() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (!imbuement) { lua_pushnil(L); return 1; @@ -83,30 +99,30 @@ int ImbuementFunctions::luaImbuementGetBase(lua_State* L) { } lua_createtable(L, 0, 7); - setField(L, "id", baseImbuement->id); - setField(L, "name", baseImbuement->name); - setField(L, "price", baseImbuement->price); - setField(L, "protection", baseImbuement->protectionPrice); - setField(L, "percent", baseImbuement->percent); - setField(L, "removeCost", baseImbuement->removeCost); - setField(L, "duration", baseImbuement->duration); + Lua::setField(L, "id", baseImbuement->id); + Lua::setField(L, "name", baseImbuement->name); + Lua::setField(L, "price", baseImbuement->price); + Lua::setField(L, "protection", baseImbuement->protectionPrice); + Lua::setField(L, "percent", baseImbuement->percent); + Lua::setField(L, "removeCost", baseImbuement->removeCost); + Lua::setField(L, "duration", baseImbuement->duration); return 1; } int ImbuementFunctions::luaImbuementGetCategory(lua_State* L) { // imbuement:getCategory() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (!imbuement) { lua_pushnil(L); return 1; } - uint16_t categoryId = imbuement->getCategory(); + const uint16_t categoryId = imbuement->getCategory(); const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(categoryId); if (categoryImbuement) { lua_createtable(L, 0, 2); - setField(L, "id", categoryImbuement->id); - setField(L, "name", categoryImbuement->name); + Lua::setField(L, "id", categoryImbuement->id); + Lua::setField(L, "name", categoryImbuement->name); } else { lua_pushnil(L); } @@ -116,19 +132,19 @@ int ImbuementFunctions::luaImbuementGetCategory(lua_State* L) { int ImbuementFunctions::luaImbuementIsPremium(lua_State* L) { // imbuement:isPremium() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (!imbuement) { lua_pushnil(L); return 1; } - pushBoolean(L, imbuement->isPremium()); + Lua::pushBoolean(L, imbuement->isPremium()); return 1; } int ImbuementFunctions::luaImbuementGetElementDamage(lua_State* L) { // imbuement:getElementDamage() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (imbuement) { lua_pushnumber(L, imbuement->elementDamage); } else { @@ -139,7 +155,7 @@ int ImbuementFunctions::luaImbuementGetElementDamage(lua_State* L) { int ImbuementFunctions::luaImbuementGetCombatType(lua_State* L) { // imbuement:getCombatType() - Imbuement* imbuement = getUserdata<Imbuement>(L, 1); + const auto* imbuement = Lua::getUserdata<Imbuement>(L, 1); if (imbuement) { lua_pushnumber(L, imbuement->combatType); } else { diff --git a/src/lua/functions/items/imbuement_functions.hpp b/src/lua/functions/items/imbuement_functions.hpp index 516fe91a3b1..7631cbb1b2f 100644 --- a/src/lua/functions/items/imbuement_functions.hpp +++ b/src/lua/functions/items/imbuement_functions.hpp @@ -9,23 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ImbuementFunctions final : LuaScriptInterface { +class ImbuementFunctions { public: - static void init(lua_State* L) { - registerClass(L, "Imbuement", "", ImbuementFunctions::luaCreateImbuement); - registerMetaMethod(L, "Imbuement", "__eq", ImbuementFunctions::luaUserdataCompare); - - registerMethod(L, "Imbuement", "getName", ImbuementFunctions::luaImbuementGetName); - registerMethod(L, "Imbuement", "getId", ImbuementFunctions::luaImbuementGetId); - registerMethod(L, "Imbuement", "getItems", ImbuementFunctions::luaImbuementGetItems); - registerMethod(L, "Imbuement", "getBase", ImbuementFunctions::luaImbuementGetBase); - registerMethod(L, "Imbuement", "getCategory", ImbuementFunctions::luaImbuementGetCategory); - registerMethod(L, "Imbuement", "isPremium", ImbuementFunctions::luaImbuementIsPremium); - registerMethod(L, "Imbuement", "getElementDamage", ImbuementFunctions::luaImbuementGetElementDamage); - registerMethod(L, "Imbuement", "getCombatType", ImbuementFunctions::luaImbuementGetCombatType); - } + static void init(lua_State* L); private: static int luaCreateImbuement(lua_State* L); diff --git a/src/lua/functions/items/item_classification_functions.cpp b/src/lua/functions/items/item_classification_functions.cpp index 4df6d6f9ea8..5d1ccea8aff 100644 --- a/src/lua/functions/items/item_classification_functions.cpp +++ b/src/lua/functions/items/item_classification_functions.cpp @@ -7,17 +7,27 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" #include "lua/functions/items/item_classification_functions.hpp" +#include "game/game.hpp" +#include "items/items_classification.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ItemClassificationFunctions::init(lua_State* L) { + Lua::registerClass(L, "ItemClassification", "", ItemClassificationFunctions::luaItemClassificationCreate); + Lua::registerMetaMethod(L, "ItemClassification", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "ItemClassification", "addTier", ItemClassificationFunctions::luaItemClassificationAddTier); +} + int ItemClassificationFunctions::luaItemClassificationCreate(lua_State* L) { // ItemClassification(id) - if (isNumber(L, 2)) { - const ItemClassification* itemClassification = g_game().getItemsClassification(getNumber<uint8_t>(L, 2), false); + if (Lua::isNumber(L, 2)) { + const ItemClassification* itemClassification = g_game().getItemsClassification(Lua::getNumber<uint8_t>(L, 2), false); if (itemClassification) { - pushUserdata<const ItemClassification>(L, itemClassification); - setMetatable(L, -1, "ItemClassification"); - pushBoolean(L, true); + Lua::pushUserdata<const ItemClassification>(L, itemClassification); + Lua::setMetatable(L, -1, "ItemClassification"); + Lua::pushBoolean(L, true); } } @@ -27,16 +37,16 @@ int ItemClassificationFunctions::luaItemClassificationCreate(lua_State* L) { int ItemClassificationFunctions::luaItemClassificationAddTier(lua_State* L) { // itemClassification:addTier(id, core, regularPrice, convergenceFusionPrice, convergenceTransferPrice) - ItemClassification* itemClassification = getUserdata<ItemClassification>(L, 1); + auto* itemClassification = Lua::getUserdata<ItemClassification>(L, 1); if (itemClassification) { itemClassification->addTier( - getNumber<uint8_t>(L, 2), - getNumber<uint8_t>(L, 3), - getNumber<uint64_t>(L, 4), - getNumber<uint64_t>(L, 5), - getNumber<uint64_t>(L, 6) + Lua::getNumber<uint8_t>(L, 2), + Lua::getNumber<uint8_t>(L, 3), + Lua::getNumber<uint64_t>(L, 4), + Lua::getNumber<uint64_t>(L, 5), + Lua::getNumber<uint64_t>(L, 6) ); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/items/item_classification_functions.hpp b/src/lua/functions/items/item_classification_functions.hpp index ebbd9fddd47..413e549a601 100644 --- a/src/lua/functions/items/item_classification_functions.hpp +++ b/src/lua/functions/items/item_classification_functions.hpp @@ -9,16 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class ItemClassificationFunctions final : LuaScriptInterface { +class ItemClassificationFunctions { public: - static void init(lua_State* L) { - registerClass(L, "ItemClassification", "", ItemClassificationFunctions::luaItemClassificationCreate); - registerMetaMethod(L, "ItemClassification", "__eq", ItemClassificationFunctions::luaUserdataCompare); - - registerMethod(L, "ItemClassification", "addTier", ItemClassificationFunctions::luaItemClassificationAddTier); - } + static void init(lua_State* L); private: static int luaItemClassificationCreate(lua_State* L); diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp index 7b5713f29b1..11d719f44f7 100644 --- a/src/lua/functions/items/item_functions.cpp +++ b/src/lua/functions/items/item_functions.cpp @@ -9,22 +9,104 @@ #include "lua/functions/items/item_functions.hpp" +#include "creatures/players/imbuements/imbuements.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" -#include "items/item.hpp" -#include "items/decay/decay.hpp" #include "game/scheduling/save_manager.hpp" +#include "items/decay/decay.hpp" +#include "items/item.hpp" +#include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ItemFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Item", "", ItemFunctions::luaItemCreate); + Lua::registerMetaMethod(L, "Item", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Item", "isItem", ItemFunctions::luaItemIsItem); + + Lua::registerMethod(L, "Item", "getContainer", ItemFunctions::luaItemGetContainer); + Lua::registerMethod(L, "Item", "getParent", ItemFunctions::luaItemGetParent); + Lua::registerMethod(L, "Item", "getTopParent", ItemFunctions::luaItemGetTopParent); + + Lua::registerMethod(L, "Item", "getId", ItemFunctions::luaItemGetId); + + Lua::registerMethod(L, "Item", "clone", ItemFunctions::luaItemClone); + Lua::registerMethod(L, "Item", "split", ItemFunctions::luaItemSplit); + Lua::registerMethod(L, "Item", "remove", ItemFunctions::luaItemRemove); + + Lua::registerMethod(L, "Item", "getUniqueId", ItemFunctions::luaItemGetUniqueId); + Lua::registerMethod(L, "Item", "getActionId", ItemFunctions::luaItemGetActionId); + Lua::registerMethod(L, "Item", "setActionId", ItemFunctions::luaItemSetActionId); + + Lua::registerMethod(L, "Item", "getCount", ItemFunctions::luaItemGetCount); + Lua::registerMethod(L, "Item", "getCharges", ItemFunctions::luaItemGetCharges); + Lua::registerMethod(L, "Item", "getFluidType", ItemFunctions::luaItemGetFluidType); + Lua::registerMethod(L, "Item", "getWeight", ItemFunctions::luaItemGetWeight); + + Lua::registerMethod(L, "Item", "getSubType", ItemFunctions::luaItemGetSubType); + + Lua::registerMethod(L, "Item", "getName", ItemFunctions::luaItemGetName); + Lua::registerMethod(L, "Item", "getPluralName", ItemFunctions::luaItemGetPluralName); + Lua::registerMethod(L, "Item", "getArticle", ItemFunctions::luaItemGetArticle); + + Lua::registerMethod(L, "Item", "getPosition", ItemFunctions::luaItemGetPosition); + Lua::registerMethod(L, "Item", "getTile", ItemFunctions::luaItemGetTile); -class Imbuement; + Lua::registerMethod(L, "Item", "hasAttribute", ItemFunctions::luaItemHasAttribute); + Lua::registerMethod(L, "Item", "getAttribute", ItemFunctions::luaItemGetAttribute); + Lua::registerMethod(L, "Item", "setAttribute", ItemFunctions::luaItemSetAttribute); + Lua::registerMethod(L, "Item", "removeAttribute", ItemFunctions::luaItemRemoveAttribute); + Lua::registerMethod(L, "Item", "getCustomAttribute", ItemFunctions::luaItemGetCustomAttribute); + Lua::registerMethod(L, "Item", "setCustomAttribute", ItemFunctions::luaItemSetCustomAttribute); + Lua::registerMethod(L, "Item", "removeCustomAttribute", ItemFunctions::luaItemRemoveCustomAttribute); + Lua::registerMethod(L, "Item", "canBeMoved", ItemFunctions::luaItemCanBeMoved); + + Lua::registerMethod(L, "Item", "setOwner", ItemFunctions::luaItemSetOwner); + Lua::registerMethod(L, "Item", "getOwnerId", ItemFunctions::luaItemGetOwnerId); + Lua::registerMethod(L, "Item", "isOwner", ItemFunctions::luaItemIsOwner); + Lua::registerMethod(L, "Item", "getOwnerName", ItemFunctions::luaItemGetOwnerName); + Lua::registerMethod(L, "Item", "hasOwner", ItemFunctions::luaItemHasOwner); + + Lua::registerMethod(L, "Item", "moveTo", ItemFunctions::luaItemMoveTo); + Lua::registerMethod(L, "Item", "transform", ItemFunctions::luaItemTransform); + Lua::registerMethod(L, "Item", "decay", ItemFunctions::luaItemDecay); + + Lua::registerMethod(L, "Item", "serializeAttributes", ItemFunctions::luaItemSerializeAttributes); + Lua::registerMethod(L, "Item", "moveToSlot", ItemFunctions::luaItemMoveToSlot); + + Lua::registerMethod(L, "Item", "getDescription", ItemFunctions::luaItemGetDescription); + + Lua::registerMethod(L, "Item", "hasProperty", ItemFunctions::luaItemHasProperty); + + Lua::registerMethod(L, "Item", "getImbuementSlot", ItemFunctions::luaItemGetImbuementSlot); + Lua::registerMethod(L, "Item", "getImbuement", ItemFunctions::luaItemGetImbuement); + + Lua::registerMethod(L, "Item", "setDuration", ItemFunctions::luaItemSetDuration); + + Lua::registerMethod(L, "Item", "isInsideDepot", ItemFunctions::luaItemIsInsideDepot); + Lua::registerMethod(L, "Item", "isContainer", ItemFunctions::luaItemIsContainer); + + Lua::registerMethod(L, "Item", "getTier", ItemFunctions::luaItemGetTier); + Lua::registerMethod(L, "Item", "setTier", ItemFunctions::luaItemSetTier); + Lua::registerMethod(L, "Item", "getClassification", ItemFunctions::luaItemGetClassification); + + Lua::registerMethod(L, "Item", "canReceiveAutoCarpet", ItemFunctions::luaItemCanReceiveAutoCarpet); + + ContainerFunctions::init(L); + ImbuementFunctions::init(L); + ItemTypeFunctions::init(L); + WeaponFunctions::init(L); +} // Item int ItemFunctions::luaItemCreate(lua_State* L) { // Item(uid) - uint32_t id = getNumber<uint32_t>(L, 2); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); - std::shared_ptr<Item> item = getScriptEnv()->getItemByUID(id); + const auto &item = Lua::getScriptEnv()->getItemByUID(id); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -33,13 +115,13 @@ int ItemFunctions::luaItemCreate(lua_State* L) { int ItemFunctions::luaItemIsItem(lua_State* L) { // item:isItem() - pushBoolean(L, getUserdataShared<const Item>(L, 1) != nullptr); + Lua::pushBoolean(L, Lua::getUserdataShared<const Item>(L, 1) != nullptr); return 1; } int ItemFunctions::luaItemGetContainer(lua_State* L) { // item:getContainer() - const auto &item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; @@ -48,53 +130,53 @@ int ItemFunctions::luaItemGetContainer(lua_State* L) { const auto &container = item->getContainer(); if (!container) { g_logger().trace("Item {} is not a container", item->getName()); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - pushUserdata(L, container); + Lua::pushUserdata(L, container); return 1; } int ItemFunctions::luaItemGetParent(lua_State* L) { // item:getParent() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Cylinder> parent = item->getParent(); + const auto &parent = item->getParent(); if (!parent) { lua_pushnil(L); return 1; } - pushCylinder(L, parent); + Lua::pushCylinder(L, parent); return 1; } int ItemFunctions::luaItemGetTopParent(lua_State* L) { // item:getTopParent() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Cylinder> topParent = item->getTopParent(); + const auto &topParent = item->getTopParent(); if (!topParent) { lua_pushnil(L); return 1; } - pushCylinder(L, topParent); + Lua::pushCylinder(L, topParent); return 1; } int ItemFunctions::luaItemGetId(lua_State* L) { // item:getId() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, item->getID()); } else { @@ -105,44 +187,44 @@ int ItemFunctions::luaItemGetId(lua_State* L) { int ItemFunctions::luaItemClone(lua_State* L) { // item:clone() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> clone = item->clone(); + const auto &clone = item->clone(); if (!clone) { lua_pushnil(L); return 1; } - getScriptEnv()->addTempItem(clone); + Lua::getScriptEnv()->addTempItem(clone); clone->setParent(VirtualCylinder::virtualCylinder); - pushUserdata<Item>(L, clone); - setItemMetatable(L, -1, clone); + Lua::pushUserdata<Item>(L, clone); + Lua::setItemMetatable(L, -1, clone); return 1; } int ItemFunctions::luaItemSplit(lua_State* L) { // item:split([count = 1]) - std::shared_ptr<Item>* itemPtr = getRawUserDataShared<Item>(L, 1); + const auto &itemPtr = Lua::getRawUserDataShared<Item>(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = *itemPtr; + const auto &item = *itemPtr; if (!item || !item->isStackable() || item->isRemoved()) { lua_pushnil(L); return 1; } - uint16_t count = std::min<uint16_t>(getNumber<uint16_t>(L, 2, 1), item->getItemCount()); - uint16_t diff = item->getItemCount() - count; + const uint16_t count = std::min<uint16_t>(Lua::getNumber<uint16_t>(L, 2, 1), item->getItemCount()); + const uint16_t diff = item->getItemCount() - count; - std::shared_ptr<Item> splitItem = item->clone(); + const auto &splitItem = item->clone(); if (!splitItem) { lua_pushnil(L); return 1; @@ -150,10 +232,10 @@ int ItemFunctions::luaItemSplit(lua_State* L) { splitItem->setItemCount(count); - ScriptEnvironment* env = getScriptEnv(); - uint32_t uid = env->addThing(item); + ScriptEnvironment* env = Lua::getScriptEnv(); + const uint32_t uid = env->addThing(item); - std::shared_ptr<Item> newItem = g_game().transformItem(item, item->getID(), diff); + const auto &newItem = g_game().transformItem(item, item->getID(), diff); if (item->isRemoved()) { env->removeItemByUID(uid); } @@ -167,17 +249,17 @@ int ItemFunctions::luaItemSplit(lua_State* L) { splitItem->setParent(VirtualCylinder::virtualCylinder); env->addTempItem(splitItem); - pushUserdata<Item>(L, splitItem); - setItemMetatable(L, -1, splitItem); + Lua::pushUserdata<Item>(L, splitItem); + Lua::setItemMetatable(L, -1, splitItem); return 1; } int ItemFunctions::luaItemRemove(lua_State* L) { // item:remove([count = -1]) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - int32_t count = getNumber<int32_t>(L, 2, -1); - pushBoolean(L, g_game().internalRemoveItem(item, count) == RETURNVALUE_NOERROR); + const auto count = Lua::getNumber<int32_t>(L, 2, -1); + Lua::pushBoolean(L, g_game().internalRemoveItem(item, count) == RETURNVALUE_NOERROR); } else { lua_pushnil(L); } @@ -186,11 +268,11 @@ int ItemFunctions::luaItemRemove(lua_State* L) { int ItemFunctions::luaItemGetUniqueId(lua_State* L) { // item:getUniqueId() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { uint32_t uniqueId = item->getAttribute<uint16_t>(ItemAttribute_t::UNIQUEID); if (uniqueId == 0) { - uniqueId = getScriptEnv()->addThing(item); + uniqueId = Lua::getScriptEnv()->addThing(item); } lua_pushnumber(L, static_cast<lua_Number>(uniqueId)); } else { @@ -201,9 +283,9 @@ int ItemFunctions::luaItemGetUniqueId(lua_State* L) { int ItemFunctions::luaItemGetActionId(lua_State* L) { // item:getActionId() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - auto actionId = item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID); + const auto actionId = item->getAttribute<uint16_t>(ItemAttribute_t::ACTIONID); lua_pushnumber(L, actionId); } else { lua_pushnil(L); @@ -213,11 +295,11 @@ int ItemFunctions::luaItemGetActionId(lua_State* L) { int ItemFunctions::luaItemSetActionId(lua_State* L) { // item:setActionId(actionId) - uint16_t actionId = getNumber<uint16_t>(L, 2); - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const uint16_t actionId = Lua::getNumber<uint16_t>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { item->setAttribute(ItemAttribute_t::ACTIONID, actionId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -226,7 +308,7 @@ int ItemFunctions::luaItemSetActionId(lua_State* L) { int ItemFunctions::luaItemGetCount(lua_State* L) { // item:getCount() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, item->getItemCount()); } else { @@ -237,7 +319,7 @@ int ItemFunctions::luaItemGetCount(lua_State* L) { int ItemFunctions::luaItemGetCharges(lua_State* L) { // item:getCharges() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, item->getCharges()); } else { @@ -248,7 +330,7 @@ int ItemFunctions::luaItemGetCharges(lua_State* L) { int ItemFunctions::luaItemGetFluidType(lua_State* L) { // item:getFluidType() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, static_cast<lua_Number>(item->getAttribute<uint16_t>(ItemAttribute_t::FLUIDTYPE))); } else { @@ -259,7 +341,7 @@ int ItemFunctions::luaItemGetFluidType(lua_State* L) { int ItemFunctions::luaItemGetWeight(lua_State* L) { // item:getWeight() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, item->getWeight()); } else { @@ -270,7 +352,7 @@ int ItemFunctions::luaItemGetWeight(lua_State* L) { int ItemFunctions::luaItemGetSubType(lua_State* L) { // item:getSubType() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { lua_pushnumber(L, item->getSubType()); } else { @@ -281,9 +363,9 @@ int ItemFunctions::luaItemGetSubType(lua_State* L) { int ItemFunctions::luaItemGetName(lua_State* L) { // item:getName() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - pushString(L, item->getName()); + Lua::pushString(L, item->getName()); } else { lua_pushnil(L); } @@ -292,9 +374,9 @@ int ItemFunctions::luaItemGetName(lua_State* L) { int ItemFunctions::luaItemGetPluralName(lua_State* L) { // item:getPluralName() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - pushString(L, item->getPluralName()); + Lua::pushString(L, item->getPluralName()); } else { lua_pushnil(L); } @@ -303,9 +385,9 @@ int ItemFunctions::luaItemGetPluralName(lua_State* L) { int ItemFunctions::luaItemGetArticle(lua_State* L) { // item:getArticle() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - pushString(L, item->getArticle()); + Lua::pushString(L, item->getArticle()); } else { lua_pushnil(L); } @@ -313,10 +395,10 @@ int ItemFunctions::luaItemGetArticle(lua_State* L) { } int ItemFunctions::luaItemGetPosition(lua_State* L) { - // item:getPosition() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + // item:Lua::getPosition() + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - pushPosition(L, item->getPosition()); + Lua::pushPosition(L, item->getPosition()); } else { lua_pushnil(L); } @@ -325,16 +407,16 @@ int ItemFunctions::luaItemGetPosition(lua_State* L) { int ItemFunctions::luaItemGetTile(lua_State* L) { // item:getTile() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Tile> tile = item->getTile(); + const auto &tile = item->getTile(); if (tile) { - pushUserdata<Tile>(L, tile); - setMetatable(L, -1, "Tile"); + Lua::pushUserdata<Tile>(L, tile); + Lua::setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } @@ -343,38 +425,38 @@ int ItemFunctions::luaItemGetTile(lua_State* L) { int ItemFunctions::luaItemHasAttribute(lua_State* L) { // item:hasAttribute(key) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } ItemAttribute_t attribute; - if (isNumber(L, 2)) { - attribute = getNumber<ItemAttribute_t>(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + attribute = Lua::getNumber<ItemAttribute_t>(L, 2); + } else if (Lua::isString(L, 2)) { + attribute = stringToItemAttribute(Lua::getString(L, 2)); } else { attribute = ItemAttribute_t::NONE; } - pushBoolean(L, item->hasAttribute(attribute)); + Lua::pushBoolean(L, item->hasAttribute(attribute)); return 1; } int ItemFunctions::luaItemGetAttribute(lua_State* L) { // item:getAttribute(key) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } ItemAttribute_t attribute; - if (isNumber(L, 2)) { - attribute = getNumber<ItemAttribute_t>(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + attribute = Lua::getNumber<ItemAttribute_t>(L, 2); + } else if (Lua::isString(L, 2)) { + attribute = stringToItemAttribute(Lua::getString(L, 2)); } else { attribute = ItemAttribute_t::NONE; } @@ -387,7 +469,7 @@ int ItemFunctions::luaItemGetAttribute(lua_State* L) { lua_pushnumber(L, static_cast<lua_Number>(item->getAttribute<int64_t>(attribute))); } else if (item->isAttributeString(attribute)) { - pushString(L, item->getAttribute<std::string>(attribute)); + Lua::pushString(L, item->getAttribute<std::string>(attribute)); } else { lua_pushnil(L); } @@ -396,17 +478,17 @@ int ItemFunctions::luaItemGetAttribute(lua_State* L) { int ItemFunctions::luaItemSetAttribute(lua_State* L) { // item:setAttribute(key, value) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } ItemAttribute_t attribute; - if (isNumber(L, 2)) { - attribute = getNumber<ItemAttribute_t>(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + attribute = Lua::getNumber<ItemAttribute_t>(L, 2); + } else if (Lua::isString(L, 2)) { + attribute = stringToItemAttribute(Lua::getString(L, 2)); } else { attribute = ItemAttribute_t::NONE; } @@ -414,39 +496,39 @@ int ItemFunctions::luaItemSetAttribute(lua_State* L) { if (item->isAttributeInteger(attribute)) { switch (attribute) { case ItemAttribute_t::DECAYSTATE: { - if (ItemDecayState_t decayState = getNumber<ItemDecayState_t>(L, 3); + if (const auto decayState = Lua::getNumber<ItemDecayState_t>(L, 3); decayState == DECAYING_FALSE || decayState == DECAYING_STOPPING) { g_decay().stopDecay(item); } else { g_decay().startDecay(item); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } case ItemAttribute_t::DURATION: { item->setDecaying(DECAYING_PENDING); - item->setDuration(getNumber<int32_t>(L, 3)); + item->setDuration(Lua::getNumber<int32_t>(L, 3)); g_decay().startDecay(item); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } case ItemAttribute_t::DURATION_TIMESTAMP: { - reportErrorFunc("Attempt to set protected key \"duration timestamp\""); - pushBoolean(L, false); + Lua::reportErrorFunc("Attempt to set protected key \"duration timestamp\""); + Lua::pushBoolean(L, false); return 1; } default: break; } - item->setAttribute(attribute, getNumber<int64_t>(L, 3)); + item->setAttribute(attribute, Lua::getNumber<int64_t>(L, 3)); item->updateTileFlags(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else if (item->isAttributeString(attribute)) { - auto newAttributeString = getString(L, 3); + const auto newAttributeString = Lua::getString(L, 3); item->setAttribute(attribute, newAttributeString); item->updateTileFlags(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -455,17 +537,17 @@ int ItemFunctions::luaItemSetAttribute(lua_State* L) { int ItemFunctions::luaItemRemoveAttribute(lua_State* L) { // item:removeAttribute(key) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } ItemAttribute_t attribute; - if (isNumber(L, 2)) { - attribute = getNumber<ItemAttribute_t>(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + attribute = Lua::getNumber<ItemAttribute_t>(L, 2); + } else if (Lua::isString(L, 2)) { + attribute = stringToItemAttribute(Lua::getString(L, 2)); } else { attribute = ItemAttribute_t::NONE; } @@ -476,28 +558,28 @@ int ItemFunctions::luaItemRemoveAttribute(lua_State* L) { if (ret) { item->removeAttribute(attribute); } else { - reportErrorFunc("Attempt to erase protected key \"duration timestamp\""); + Lua::reportErrorFunc("Attempt to erase protected key \"duration timestamp\""); } } else { - reportErrorFunc("Attempt to erase protected key \"uid\""); + Lua::reportErrorFunc("Attempt to erase protected key \"uid\""); } - pushBoolean(L, ret); + Lua::pushBoolean(L, ret); return 1; } int ItemFunctions::luaItemGetCustomAttribute(lua_State* L) { // item:getCustomAttribute(key) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } const CustomAttribute* customAttribute; - if (isNumber(L, 2)) { - customAttribute = item->getCustomAttribute(std::to_string(getNumber<int64_t>(L, 2))); - } else if (isString(L, 2)) { - customAttribute = item->getCustomAttribute(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + customAttribute = item->getCustomAttribute(std::to_string(Lua::getNumber<int64_t>(L, 2))); + } else if (Lua::isString(L, 2)) { + customAttribute = item->getCustomAttribute(Lua::getString(L, 2)); } else { lua_pushnil(L); return 1; @@ -513,57 +595,57 @@ int ItemFunctions::luaItemGetCustomAttribute(lua_State* L) { int ItemFunctions::luaItemSetCustomAttribute(lua_State* L) { // item:setCustomAttribute(key, value) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } std::string key; - if (isNumber(L, 2)) { - key = std::to_string(getNumber<int64_t>(L, 2)); - } else if (isString(L, 2)) { - key = getString(L, 2); + if (Lua::isNumber(L, 2)) { + key = std::to_string(Lua::getNumber<int64_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + key = Lua::getString(L, 2); } else { lua_pushnil(L); return 1; } - if (isNumber(L, 3)) { - const double doubleValue = getNumber<double>(L, 3); + if (Lua::isNumber(L, 3)) { + const double doubleValue = Lua::getNumber<double>(L, 3); if (std::floor(doubleValue) < doubleValue) { item->setCustomAttribute(key, doubleValue); } else { - int64_t int64 = getNumber<int64_t>(L, 3); + const int64_t int64 = Lua::getNumber<int64_t>(L, 3); item->setCustomAttribute(key, int64); } - } else if (isString(L, 3)) { - const std::string stringValue = getString(L, 3); + } else if (Lua::isString(L, 3)) { + const std::string stringValue = Lua::getString(L, 3); item->setCustomAttribute(key, stringValue); - } else if (isBoolean(L, 3)) { - const bool boolValue = getBoolean(L, 3); + } else if (Lua::isBoolean(L, 3)) { + const bool boolValue = Lua::getBoolean(L, 3); item->setCustomAttribute(key, boolValue); } else { lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ItemFunctions::luaItemRemoveCustomAttribute(lua_State* L) { // item:removeCustomAttribute(key) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; } - if (isNumber(L, 2)) { - pushBoolean(L, item->removeCustomAttribute(std::to_string(getNumber<int64_t>(L, 2)))); - } else if (isString(L, 2)) { - pushBoolean(L, item->removeCustomAttribute(getString(L, 2))); + if (Lua::isNumber(L, 2)) { + Lua::pushBoolean(L, item->removeCustomAttribute(std::to_string(Lua::getNumber<int64_t>(L, 2)))); + } else if (Lua::isString(L, 2)) { + Lua::pushBoolean(L, item->removeCustomAttribute(Lua::getString(L, 2))); } else { lua_pushnil(L); } @@ -572,9 +654,9 @@ int ItemFunctions::luaItemRemoveCustomAttribute(lua_State* L) { int ItemFunctions::luaItemCanBeMoved(lua_State* L) { // item:canBeMoved() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - pushBoolean(L, item->canBeMoved()); + Lua::pushBoolean(L, item->canBeMoved()); } else { lua_pushnil(L); } @@ -583,7 +665,7 @@ int ItemFunctions::luaItemCanBeMoved(lua_State* L) { int ItemFunctions::luaItemSerializeAttributes(lua_State* L) { // item:serializeAttributes() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { lua_pushnil(L); return 1; @@ -600,37 +682,37 @@ int ItemFunctions::luaItemSerializeAttributes(lua_State* L) { int ItemFunctions::luaItemMoveTo(lua_State* L) { // item:moveTo(position or cylinder[, flags]) - std::shared_ptr<Item>* itemPtr = getRawUserDataShared<Item>(L, 1); + const auto &itemPtr = Lua::getRawUserDataShared<Item>(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = *itemPtr; + const auto &item = *itemPtr; if (!item || item->isRemoved()) { lua_pushnil(L); return 1; } std::shared_ptr<Cylinder> toCylinder; - if (isUserdata(L, 2)) { - const LuaData_t type = getUserdataType(L, 2); + if (Lua::isUserdata(L, 2)) { + const LuaData_t type = Lua::getUserdataType(L, 2); switch (type) { case LuaData_t::Container: - toCylinder = getUserdataShared<Container>(L, 2); + toCylinder = Lua::getUserdataShared<Container>(L, 2); break; case LuaData_t::Player: - toCylinder = getUserdataShared<Player>(L, 2); + toCylinder = Lua::getUserdataShared<Player>(L, 2); break; case LuaData_t::Tile: - toCylinder = getUserdataShared<Tile>(L, 2); + toCylinder = Lua::getUserdataShared<Tile>(L, 2); break; default: toCylinder = nullptr; break; } } else { - toCylinder = g_game().map.getTile(getPosition(L, 2)); + toCylinder = g_game().map.getTile(Lua::getPosition(L, 2)); } if (!toCylinder) { @@ -639,53 +721,53 @@ int ItemFunctions::luaItemMoveTo(lua_State* L) { } if (item->getParent() == toCylinder) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } - uint32_t flags = getNumber<uint32_t>(L, 3, FLAG_NOLIMIT | FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE | FLAG_IGNORENOTMOVABLE); + const auto flags = Lua::getNumber<uint32_t>(L, 3, FLAG_NOLIMIT | FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE | FLAG_IGNORENOTMOVABLE); if (item->getParent() == VirtualCylinder::virtualCylinder) { - pushBoolean(L, g_game().internalAddItem(toCylinder, item, INDEX_WHEREEVER, flags) == RETURNVALUE_NOERROR); + Lua::pushBoolean(L, g_game().internalAddItem(toCylinder, item, INDEX_WHEREEVER, flags) == RETURNVALUE_NOERROR); } else { std::shared_ptr<Item> moveItem = nullptr; ReturnValue ret = g_game().internalMoveItem(item->getParent(), toCylinder, INDEX_WHEREEVER, item, item->getItemCount(), &moveItem, flags); if (moveItem) { *itemPtr = moveItem; } - pushBoolean(L, ret == RETURNVALUE_NOERROR); + Lua::pushBoolean(L, ret == RETURNVALUE_NOERROR); } return 1; } int ItemFunctions::luaItemTransform(lua_State* L) { // item:transform(itemId[, count/subType = -1]) - std::shared_ptr<Item>* itemPtr = getRawUserDataShared<Item>(L, 1); + const auto &itemPtr = Lua::getRawUserDataShared<Item>(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> &item = *itemPtr; + auto &item = *itemPtr; if (!item) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t subType = getNumber<int32_t>(L, 3, -1); + auto subType = Lua::getNumber<int32_t>(L, 3, -1); if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -694,10 +776,10 @@ int ItemFunctions::luaItemTransform(lua_State* L) { subType = std::min<int32_t>(subType, it.stackSize); } - ScriptEnvironment* env = getScriptEnv(); - uint32_t uid = env->addThing(item); + ScriptEnvironment* env = Lua::getScriptEnv(); + const uint32_t uid = env->addThing(item); - std::shared_ptr<Item> newItem = g_game().transformItem(item, itemId, subType); + const auto &newItem = g_game().transformItem(item, itemId, subType); if (item->isRemoved()) { env->removeItemByUID(uid); } @@ -707,21 +789,21 @@ int ItemFunctions::luaItemTransform(lua_State* L) { } item = newItem; - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ItemFunctions::luaItemDecay(lua_State* L) { // item:decay(decayId) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - if (isNumber(L, 2)) { + if (Lua::isNumber(L, 2)) { ItemType &it = Item::items.getItemType(item->getID()); - it.decayTo = getNumber<int32_t>(L, 2); + it.decayTo = Lua::getNumber<int32_t>(L, 2); } item->startDecaying(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -730,36 +812,32 @@ int ItemFunctions::luaItemDecay(lua_State* L) { int ItemFunctions::luaItemMoveToSlot(lua_State* L) { // item:moveToSlot(player, slot) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item || item->isRemoved()) { lua_pushnil(L); return 1; } - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 2); + const auto &player = Lua::getUserdataShared<Player>(L, 2); if (!player) { lua_pushnil(L); return 1; } - Slots_t slot = getNumber<Slots_t>(L, 3, CONST_SLOT_WHEREEVER); + const auto slot = Lua::getNumber<Slots_t>(L, 3, CONST_SLOT_WHEREEVER); - std::shared_ptr<Item> moveItem = nullptr; ReturnValue ret = g_game().internalMoveItem(item->getParent(), player, slot, item, item->getItemCount(), nullptr); - if (moveItem) { - item = moveItem; - } - pushBoolean(L, ret == RETURNVALUE_NOERROR); + Lua::pushBoolean(L, ret == RETURNVALUE_NOERROR); return 1; } int ItemFunctions::luaItemGetDescription(lua_State* L) { // item:getDescription(distance) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - int32_t distance = getNumber<int32_t>(L, 2); - pushString(L, item->getDescription(distance)); + const int32_t distance = Lua::getNumber<int32_t>(L, 2); + Lua::pushString(L, item->getDescription(distance)); } else { lua_pushnil(L); } @@ -768,10 +846,10 @@ int ItemFunctions::luaItemGetDescription(lua_State* L) { int ItemFunctions::luaItemHasProperty(lua_State* L) { // item:hasProperty(property) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (item) { - ItemProperty property = getNumber<ItemProperty>(L, 2); - pushBoolean(L, item->hasProperty(property)); + const ItemProperty property = Lua::getNumber<ItemProperty>(L, 2); + Lua::pushBoolean(L, item->hasProperty(property)); } else { lua_pushnil(L); } @@ -780,10 +858,10 @@ int ItemFunctions::luaItemHasProperty(lua_State* L) { int ItemFunctions::luaItemGetImbuement(lua_State* L) { // item:getImbuement() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -798,23 +876,23 @@ int ItemFunctions::luaItemGetImbuement(lua_State* L) { continue; } - pushUserdata<Imbuement>(L, imbuement); - setMetatable(L, -1, "Imbuement"); + Lua::pushUserdata<Imbuement>(L, imbuement); + Lua::setMetatable(L, -1, "Imbuement"); lua_createtable(L, 0, 3); - setField(L, "id", imbuement->getID()); - setField(L, "name", imbuement->getName()); - setField(L, "duration", static_cast<lua_Number>(imbuementInfo.duration)); + Lua::setField(L, "id", imbuement->getID()); + Lua::setField(L, "name", imbuement->getName()); + Lua::setField(L, "duration", static_cast<lua_Number>(imbuementInfo.duration)); } return 1; } int ItemFunctions::luaItemGetImbuementSlot(lua_State* L) { // item:getImbuementSlot() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -825,26 +903,26 @@ int ItemFunctions::luaItemGetImbuementSlot(lua_State* L) { int ItemFunctions::luaItemSetDuration(lua_State* L) { // item:setDuration(minDuration, maxDuration = 0, decayTo = 0, showDuration = true) // Example: item:setDuration(10000, 20000, 2129, false) = random duration from range 10000/20000 - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - uint32_t minDuration = getNumber<uint32_t>(L, 2); + const uint32_t minDuration = Lua::getNumber<uint32_t>(L, 2); uint32_t maxDuration = 0; if (lua_gettop(L) > 2) { - maxDuration = uniform_random(minDuration, getNumber<uint32_t>(L, 3)); + maxDuration = uniform_random(minDuration, Lua::getNumber<uint32_t>(L, 3)); } uint16_t itemid = 0; if (lua_gettop(L) > 3) { - itemid = getNumber<uint16_t>(L, 4); + itemid = Lua::getNumber<uint16_t>(L, 4); } bool showDuration = true; if (lua_gettop(L) > 4) { - showDuration = getBoolean(L, 5); + showDuration = Lua::getBoolean(L, 5); } ItemType &it = Item::items.getItemType(item->getID()); @@ -856,43 +934,43 @@ int ItemFunctions::luaItemSetDuration(lua_State* L) { it.showDuration = showDuration; it.decayTo = itemid; item->startDecaying(); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int ItemFunctions::luaItemIsInsideDepot(lua_State* L) { // item:isInsideDepot([includeInbox = false]) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, item->isInsideDepot(getBoolean(L, 2, false))); + Lua::pushBoolean(L, item->isInsideDepot(Lua::getBoolean(L, 2, false))); return 1; } int ItemFunctions::luaItemIsContainer(lua_State* L) { // item:isContainer() - const auto item = getUserdataShared<const Item>(L, 1); + const auto &item = Lua::getUserdataShared<const Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } const auto &it = Item::items[item->getID()]; - pushBoolean(L, it.isContainer()); + Lua::pushBoolean(L, it.isContainer()); return 1; } int ItemFunctions::luaItemGetTier(lua_State* L) { // item:getTier() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -902,24 +980,24 @@ int ItemFunctions::luaItemGetTier(lua_State* L) { int ItemFunctions::luaItemSetTier(lua_State* L) { // item:setTier(tier) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - item->setTier(getNumber<uint8_t>(L, 2)); - pushBoolean(L, true); + item->setTier(Lua::getNumber<uint8_t>(L, 2)); + Lua::pushBoolean(L, true); return 1; } int ItemFunctions::luaItemGetClassification(lua_State* L) { // item:getClassification() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } @@ -929,56 +1007,56 @@ int ItemFunctions::luaItemGetClassification(lua_State* L) { int ItemFunctions::luaItemCanReceiveAutoCarpet(lua_State* L) { // item:canReceiveAutoCarpet() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, item->canReceiveAutoCarpet()); + Lua::pushBoolean(L, item->canReceiveAutoCarpet()); return 1; } int ItemFunctions::luaItemSetOwner(lua_State* L) { // item:setOwner(creature|creatureId) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 0; } - if (isUserdata(L, 2)) { - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 2); + if (Lua::isUserdata(L, 2)) { + const auto &creature = Lua::getUserdataShared<Creature>(L, 2); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 0; } item->setOwner(creature); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } - auto creatureId = getNumber<uint32_t>(L, 2); + const auto creatureId = Lua::getNumber<uint32_t>(L, 2); if (creatureId != 0) { item->setOwner(creatureId); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } int ItemFunctions::luaItemGetOwnerId(lua_State* L) { // item:getOwner() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 0; } - if (auto ownerId = item->getOwnerId()) { + if (const auto ownerId = item->getOwnerId()) { lua_pushnumber(L, ownerId); return 1; } @@ -989,42 +1067,42 @@ int ItemFunctions::luaItemGetOwnerId(lua_State* L) { int ItemFunctions::luaItemIsOwner(lua_State* L) { // item:isOwner(creature|creatureId) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 0; } - if (isUserdata(L, 2)) { - std::shared_ptr<Creature> creature = getUserdataShared<Creature>(L, 2); + if (Lua::isUserdata(L, 2)) { + const auto &creature = Lua::getUserdataShared<Creature>(L, 2); if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 0; } - pushBoolean(L, item->isOwner(creature)); + Lua::pushBoolean(L, item->isOwner(creature)); return 1; } - auto creatureId = getNumber<uint32_t>(L, 2); + const auto creatureId = Lua::getNumber<uint32_t>(L, 2); if (creatureId != 0) { - pushBoolean(L, item->isOwner(creatureId)); + Lua::pushBoolean(L, item->isOwner(creatureId)); return 1; } - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } int ItemFunctions::luaItemGetOwnerName(lua_State* L) { // item:getOwnerName() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 0; } - if (auto ownerName = item->getOwnerName(); !ownerName.empty()) { - pushString(L, ownerName); + if (const auto ownerName = item->getOwnerName(); !ownerName.empty()) { + Lua::pushString(L, ownerName); return 1; } @@ -1034,12 +1112,12 @@ int ItemFunctions::luaItemGetOwnerName(lua_State* L) { int ItemFunctions::luaItemHasOwner(lua_State* L) { // item:hasOwner() - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 1); + const auto &item = Lua::getUserdataShared<Item>(L, 1); if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); return 1; } - pushBoolean(L, item->hasOwner()); + Lua::pushBoolean(L, item->hasOwner()); return 1; } diff --git a/src/lua/functions/items/item_functions.hpp b/src/lua/functions/items/item_functions.hpp index ab3e91e1648..44b97c0e113 100644 --- a/src/lua/functions/items/item_functions.hpp +++ b/src/lua/functions/items/item_functions.hpp @@ -13,89 +13,9 @@ #include "lua/functions/items/imbuement_functions.hpp" #include "lua/functions/items/item_type_functions.hpp" #include "lua/functions/items/weapon_functions.hpp" -#include "lua/scripts/luascript.hpp" - -class ItemFunctions final : LuaScriptInterface { +class ItemFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Item", "", ItemFunctions::luaItemCreate); - registerMetaMethod(L, "Item", "__eq", ItemFunctions::luaUserdataCompare); - - registerMethod(L, "Item", "isItem", ItemFunctions::luaItemIsItem); - - registerMethod(L, "Item", "getContainer", ItemFunctions::luaItemGetContainer); - registerMethod(L, "Item", "getParent", ItemFunctions::luaItemGetParent); - registerMethod(L, "Item", "getTopParent", ItemFunctions::luaItemGetTopParent); - - registerMethod(L, "Item", "getId", ItemFunctions::luaItemGetId); - - registerMethod(L, "Item", "clone", ItemFunctions::luaItemClone); - registerMethod(L, "Item", "split", ItemFunctions::luaItemSplit); - registerMethod(L, "Item", "remove", ItemFunctions::luaItemRemove); - - registerMethod(L, "Item", "getUniqueId", ItemFunctions::luaItemGetUniqueId); - registerMethod(L, "Item", "getActionId", ItemFunctions::luaItemGetActionId); - registerMethod(L, "Item", "setActionId", ItemFunctions::luaItemSetActionId); - - registerMethod(L, "Item", "getCount", ItemFunctions::luaItemGetCount); - registerMethod(L, "Item", "getCharges", ItemFunctions::luaItemGetCharges); - registerMethod(L, "Item", "getFluidType", ItemFunctions::luaItemGetFluidType); - registerMethod(L, "Item", "getWeight", ItemFunctions::luaItemGetWeight); - - registerMethod(L, "Item", "getSubType", ItemFunctions::luaItemGetSubType); - - registerMethod(L, "Item", "getName", ItemFunctions::luaItemGetName); - registerMethod(L, "Item", "getPluralName", ItemFunctions::luaItemGetPluralName); - registerMethod(L, "Item", "getArticle", ItemFunctions::luaItemGetArticle); - - registerMethod(L, "Item", "getPosition", ItemFunctions::luaItemGetPosition); - registerMethod(L, "Item", "getTile", ItemFunctions::luaItemGetTile); - - registerMethod(L, "Item", "hasAttribute", ItemFunctions::luaItemHasAttribute); - registerMethod(L, "Item", "getAttribute", ItemFunctions::luaItemGetAttribute); - registerMethod(L, "Item", "setAttribute", ItemFunctions::luaItemSetAttribute); - registerMethod(L, "Item", "removeAttribute", ItemFunctions::luaItemRemoveAttribute); - registerMethod(L, "Item", "getCustomAttribute", ItemFunctions::luaItemGetCustomAttribute); - registerMethod(L, "Item", "setCustomAttribute", ItemFunctions::luaItemSetCustomAttribute); - registerMethod(L, "Item", "removeCustomAttribute", ItemFunctions::luaItemRemoveCustomAttribute); - registerMethod(L, "Item", "canBeMoved", ItemFunctions::luaItemCanBeMoved); - - registerMethod(L, "Item", "setOwner", ItemFunctions::luaItemSetOwner); - registerMethod(L, "Item", "getOwnerId", ItemFunctions::luaItemGetOwnerId); - registerMethod(L, "Item", "isOwner", ItemFunctions::luaItemIsOwner); - registerMethod(L, "Item", "getOwnerName", ItemFunctions::luaItemGetOwnerName); - registerMethod(L, "Item", "hasOwner", ItemFunctions::luaItemHasOwner); - - registerMethod(L, "Item", "moveTo", ItemFunctions::luaItemMoveTo); - registerMethod(L, "Item", "transform", ItemFunctions::luaItemTransform); - registerMethod(L, "Item", "decay", ItemFunctions::luaItemDecay); - - registerMethod(L, "Item", "serializeAttributes", ItemFunctions::luaItemSerializeAttributes); - registerMethod(L, "Item", "moveToSlot", ItemFunctions::luaItemMoveToSlot); - - registerMethod(L, "Item", "getDescription", ItemFunctions::luaItemGetDescription); - - registerMethod(L, "Item", "hasProperty", ItemFunctions::luaItemHasProperty); - - registerMethod(L, "Item", "getImbuementSlot", ItemFunctions::luaItemGetImbuementSlot); - registerMethod(L, "Item", "getImbuement", ItemFunctions::luaItemGetImbuement); - - registerMethod(L, "Item", "setDuration", ItemFunctions::luaItemSetDuration); - - registerMethod(L, "Item", "isInsideDepot", ItemFunctions::luaItemIsInsideDepot); - registerMethod(L, "Item", "isContainer", ItemFunctions::luaItemIsContainer); - - registerMethod(L, "Item", "getTier", ItemFunctions::luaItemGetTier); - registerMethod(L, "Item", "setTier", ItemFunctions::luaItemSetTier); - registerMethod(L, "Item", "getClassification", ItemFunctions::luaItemGetClassification); - - registerMethod(L, "Item", "canReceiveAutoCarpet", ItemFunctions::luaItemCanReceiveAutoCarpet); - - ContainerFunctions::init(L); - ImbuementFunctions::init(L); - ItemTypeFunctions::init(L); - WeaponFunctions::init(L); - } + static void init(lua_State* L); private: static int luaItemCreate(lua_State* L); diff --git a/src/lua/functions/items/item_type_functions.cpp b/src/lua/functions/items/item_type_functions.cpp index 333e00bf763..1669e6b795e 100644 --- a/src/lua/functions/items/item_type_functions.cpp +++ b/src/lua/functions/items/item_type_functions.cpp @@ -7,30 +7,100 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/items/item_type_functions.hpp" + #include "items/item.hpp" #include "items/items.hpp" -#include "lua/functions/items/item_type_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void ItemTypeFunctions::init(lua_State* L) { + Lua::registerClass(L, "ItemType", "", ItemTypeFunctions::luaItemTypeCreate); + Lua::registerMetaMethod(L, "ItemType", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "ItemType", "isCorpse", ItemTypeFunctions::luaItemTypeIsCorpse); + Lua::registerMethod(L, "ItemType", "isDoor", ItemTypeFunctions::luaItemTypeIsDoor); + Lua::registerMethod(L, "ItemType", "isContainer", ItemTypeFunctions::luaItemTypeIsContainer); + Lua::registerMethod(L, "ItemType", "isFluidContainer", ItemTypeFunctions::luaItemTypeIsFluidContainer); + Lua::registerMethod(L, "ItemType", "isMovable", ItemTypeFunctions::luaItemTypeIsMovable); + Lua::registerMethod(L, "ItemType", "isRune", ItemTypeFunctions::luaItemTypeIsRune); + Lua::registerMethod(L, "ItemType", "isStackable", ItemTypeFunctions::luaItemTypeIsStackable); + Lua::registerMethod(L, "ItemType", "isStowable", ItemTypeFunctions::luaItemTypeIsStowable); + Lua::registerMethod(L, "ItemType", "isReadable", ItemTypeFunctions::luaItemTypeIsReadable); + Lua::registerMethod(L, "ItemType", "isWritable", ItemTypeFunctions::luaItemTypeIsWritable); + Lua::registerMethod(L, "ItemType", "isBlocking", ItemTypeFunctions::luaItemTypeIsBlocking); + Lua::registerMethod(L, "ItemType", "isGroundTile", ItemTypeFunctions::luaItemTypeIsGroundTile); + Lua::registerMethod(L, "ItemType", "isMagicField", ItemTypeFunctions::luaItemTypeIsMagicField); + Lua::registerMethod(L, "ItemType", "isMultiUse", ItemTypeFunctions::luaItemTypeIsMultiUse); + Lua::registerMethod(L, "ItemType", "isPickupable", ItemTypeFunctions::luaItemTypeIsPickupable); + Lua::registerMethod(L, "ItemType", "isKey", ItemTypeFunctions::luaItemTypeIsKey); + Lua::registerMethod(L, "ItemType", "isQuiver", ItemTypeFunctions::luaItemTypeIsQuiver); + + Lua::registerMethod(L, "ItemType", "getType", ItemTypeFunctions::luaItemTypeGetType); + Lua::registerMethod(L, "ItemType", "getId", ItemTypeFunctions::luaItemTypeGetId); + Lua::registerMethod(L, "ItemType", "getName", ItemTypeFunctions::luaItemTypeGetName); + Lua::registerMethod(L, "ItemType", "getPluralName", ItemTypeFunctions::luaItemTypeGetPluralName); + Lua::registerMethod(L, "ItemType", "getArticle", ItemTypeFunctions::luaItemTypeGetArticle); + Lua::registerMethod(L, "ItemType", "getDescription", ItemTypeFunctions::luaItemTypeGetDescription); + Lua::registerMethod(L, "ItemType", "getSlotPosition", ItemTypeFunctions::luaItemTypeGetSlotPosition); + + Lua::registerMethod(L, "ItemType", "getCharges", ItemTypeFunctions::luaItemTypeGetCharges); + Lua::registerMethod(L, "ItemType", "getFluidSource", ItemTypeFunctions::luaItemTypeGetFluidSource); + Lua::registerMethod(L, "ItemType", "getCapacity", ItemTypeFunctions::luaItemTypeGetCapacity); + Lua::registerMethod(L, "ItemType", "getWeight", ItemTypeFunctions::luaItemTypeGetWeight); + Lua::registerMethod(L, "ItemType", "getStackSize", ItemTypeFunctions::luaItemTypeGetStackSize); + + Lua::registerMethod(L, "ItemType", "getHitChance", ItemTypeFunctions::luaItemTypeGetHitChance); + Lua::registerMethod(L, "ItemType", "getShootRange", ItemTypeFunctions::luaItemTypeGetShootRange); + + Lua::registerMethod(L, "ItemType", "getAttack", ItemTypeFunctions::luaItemTypeGetAttack); + Lua::registerMethod(L, "ItemType", "getDefense", ItemTypeFunctions::luaItemTypeGetDefense); + Lua::registerMethod(L, "ItemType", "getExtraDefense", ItemTypeFunctions::luaItemTypeGetExtraDefense); + Lua::registerMethod(L, "ItemType", "getImbuementSlot", ItemTypeFunctions::luaItemTypeGetImbuementSlot); + Lua::registerMethod(L, "ItemType", "getArmor", ItemTypeFunctions::luaItemTypeGetArmor); + Lua::registerMethod(L, "ItemType", "getWeaponType", ItemTypeFunctions::luaItemTypeGetWeaponType); + + Lua::registerMethod(L, "ItemType", "getElementType", ItemTypeFunctions::luaItemTypeGetElementType); + Lua::registerMethod(L, "ItemType", "getElementDamage", ItemTypeFunctions::luaItemTypeGetElementDamage); + + Lua::registerMethod(L, "ItemType", "getTransformEquipId", ItemTypeFunctions::luaItemTypeGetTransformEquipId); + Lua::registerMethod(L, "ItemType", "getTransformDeEquipId", ItemTypeFunctions::luaItemTypeGetTransformDeEquipId); + Lua::registerMethod(L, "ItemType", "getDestroyId", ItemTypeFunctions::luaItemTypeGetDestroyId); + Lua::registerMethod(L, "ItemType", "getDecayId", ItemTypeFunctions::luaItemTypeGetDecayId); + Lua::registerMethod(L, "ItemType", "getRequiredLevel", ItemTypeFunctions::luaItemTypeGetRequiredLevel); + Lua::registerMethod(L, "ItemType", "getAmmoType", ItemTypeFunctions::luaItemTypeGetAmmoType); + + Lua::registerMethod(L, "ItemType", "getDecayTime", ItemTypeFunctions::luaItemTypeGetDecayTime); + Lua::registerMethod(L, "ItemType", "getShowDuration", ItemTypeFunctions::luaItemTypeGetShowDuration); + Lua::registerMethod(L, "ItemType", "getWrapableTo", ItemTypeFunctions::luaItemTypeGetWrapableTo); + Lua::registerMethod(L, "ItemType", "getSpeed", ItemTypeFunctions::luaItemTypeGetSpeed); + Lua::registerMethod(L, "ItemType", "getBaseSpeed", ItemTypeFunctions::luaItemTypeGetBaseSpeed); + Lua::registerMethod(L, "ItemType", "getVocationString", ItemTypeFunctions::luaItemTypeGetVocationString); + + Lua::registerMethod(L, "ItemType", "hasSubType", ItemTypeFunctions::luaItemTypeHasSubType); + + ItemClassificationFunctions::init(L); +} int ItemTypeFunctions::luaItemTypeCreate(lua_State* L) { // ItemType(id or name) uint32_t id; - if (isNumber(L, 2)) { - id = getNumber<uint32_t>(L, 2); + if (Lua::isNumber(L, 2)) { + id = Lua::getNumber<uint32_t>(L, 2); } else { - id = Item::items.getItemIdByName(getString(L, 2)); + id = Item::items.getItemIdByName(Lua::getString(L, 2)); } const ItemType &itemType = Item::items[id]; - pushUserdata<const ItemType>(L, &itemType); - setMetatable(L, -1, "ItemType"); + Lua::pushUserdata<const ItemType>(L, &itemType); + Lua::setMetatable(L, -1, "ItemType"); return 1; } int ItemTypeFunctions::luaItemTypeIsCorpse(lua_State* L) { // itemType:isCorpse() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isCorpse); + Lua::pushBoolean(L, itemType->isCorpse); } else { lua_pushnil(L); } @@ -39,9 +109,9 @@ int ItemTypeFunctions::luaItemTypeIsCorpse(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsDoor(lua_State* L) { // itemType:isDoor() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isDoor()); + Lua::pushBoolean(L, itemType->isDoor()); } else { lua_pushnil(L); } @@ -50,9 +120,9 @@ int ItemTypeFunctions::luaItemTypeIsDoor(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsContainer(lua_State* L) { // itemType:isContainer() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isContainer()); + Lua::pushBoolean(L, itemType->isContainer()); } else { lua_pushnil(L); } @@ -61,9 +131,9 @@ int ItemTypeFunctions::luaItemTypeIsContainer(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsFluidContainer(lua_State* L) { // itemType:isFluidContainer() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isFluidContainer()); + Lua::pushBoolean(L, itemType->isFluidContainer()); } else { lua_pushnil(L); } @@ -72,9 +142,9 @@ int ItemTypeFunctions::luaItemTypeIsFluidContainer(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsMovable(lua_State* L) { // itemType:isMovable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->movable); + Lua::pushBoolean(L, itemType->movable); } else { lua_pushnil(L); } @@ -83,9 +153,9 @@ int ItemTypeFunctions::luaItemTypeIsMovable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsRune(lua_State* L) { // itemType:isRune() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isRune()); + Lua::pushBoolean(L, itemType->isRune()); } else { lua_pushnil(L); } @@ -94,9 +164,9 @@ int ItemTypeFunctions::luaItemTypeIsRune(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsStackable(lua_State* L) { // itemType:isStackable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->stackable); + Lua::pushBoolean(L, itemType->stackable); } else { lua_pushnil(L); } @@ -105,9 +175,9 @@ int ItemTypeFunctions::luaItemTypeIsStackable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsStowable(lua_State* L) { // itemType:isStowable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->stackable && itemType->wareId > 0); + Lua::pushBoolean(L, itemType->stackable && itemType->wareId > 0); } else { lua_pushnil(L); } @@ -116,9 +186,9 @@ int ItemTypeFunctions::luaItemTypeIsStowable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsReadable(lua_State* L) { // itemType:isReadable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->canReadText); + Lua::pushBoolean(L, itemType->canReadText); } else { lua_pushnil(L); } @@ -127,9 +197,9 @@ int ItemTypeFunctions::luaItemTypeIsReadable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsWritable(lua_State* L) { // itemType:isWritable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->canWriteText); + Lua::pushBoolean(L, itemType->canWriteText); } else { lua_pushnil(L); } @@ -138,9 +208,9 @@ int ItemTypeFunctions::luaItemTypeIsWritable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsBlocking(lua_State* L) { // itemType:isBlocking() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->blockProjectile || itemType->blockSolid); + Lua::pushBoolean(L, itemType->blockProjectile || itemType->blockSolid); } else { lua_pushnil(L); } @@ -149,9 +219,9 @@ int ItemTypeFunctions::luaItemTypeIsBlocking(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsGroundTile(lua_State* L) { // itemType:isGroundTile() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isGroundTile()); + Lua::pushBoolean(L, itemType->isGroundTile()); } else { lua_pushnil(L); } @@ -160,9 +230,9 @@ int ItemTypeFunctions::luaItemTypeIsGroundTile(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsMagicField(lua_State* L) { // itemType:isMagicField() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isMagicField()); + Lua::pushBoolean(L, itemType->isMagicField()); } else { lua_pushnil(L); } @@ -171,9 +241,9 @@ int ItemTypeFunctions::luaItemTypeIsMagicField(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsMultiUse(lua_State* L) { // itemType:isMultiUse() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isMultiUse()); + Lua::pushBoolean(L, itemType->isMultiUse()); } else { lua_pushnil(L); } @@ -182,9 +252,9 @@ int ItemTypeFunctions::luaItemTypeIsMultiUse(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsPickupable(lua_State* L) { // itemType:isPickupable() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isPickupable()); + Lua::pushBoolean(L, itemType->isPickupable()); } else { lua_pushnil(L); } @@ -193,9 +263,9 @@ int ItemTypeFunctions::luaItemTypeIsPickupable(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsKey(lua_State* L) { // itemType:isKey() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isKey()); + Lua::pushBoolean(L, itemType->isKey()); } else { lua_pushnil(L); } @@ -204,9 +274,9 @@ int ItemTypeFunctions::luaItemTypeIsKey(lua_State* L) { int ItemTypeFunctions::luaItemTypeIsQuiver(lua_State* L) { // itemType:isQuiver() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->isQuiver()); + Lua::pushBoolean(L, itemType->isQuiver()); } else { lua_pushnil(L); } @@ -215,7 +285,7 @@ int ItemTypeFunctions::luaItemTypeIsQuiver(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetType(lua_State* L) { // itemType:getType() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->type); } else { @@ -226,7 +296,7 @@ int ItemTypeFunctions::luaItemTypeGetType(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetId(lua_State* L) { // itemType:getId() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->id); } else { @@ -237,9 +307,9 @@ int ItemTypeFunctions::luaItemTypeGetId(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetName(lua_State* L) { // itemType:getName() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushString(L, itemType->name); + Lua::pushString(L, itemType->name); } else { lua_pushnil(L); } @@ -248,9 +318,9 @@ int ItemTypeFunctions::luaItemTypeGetName(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetPluralName(lua_State* L) { // itemType:getPluralName() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushString(L, itemType->getPluralName()); + Lua::pushString(L, itemType->getPluralName()); } else { lua_pushnil(L); } @@ -259,9 +329,9 @@ int ItemTypeFunctions::luaItemTypeGetPluralName(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetArticle(lua_State* L) { // itemType:getArticle() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushString(L, itemType->article); + Lua::pushString(L, itemType->article); } else { lua_pushnil(L); } @@ -270,11 +340,11 @@ int ItemTypeFunctions::luaItemTypeGetArticle(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetDescription(lua_State* L) { // itemType:getDescription([count]) - auto itemType = getUserdata<ItemType>(L, 1); + const auto &itemType = Lua::getUserdata<ItemType>(L, 1); if (itemType) { - auto count = getNumber<uint16_t>(L, 2, -1); - auto description = Item::getDescription(*itemType, 1, nullptr, count); - pushString(L, description); + const auto count = Lua::getNumber<uint16_t>(L, 2, -1); + const auto description = Item::getDescription(*itemType, 1, nullptr, count); + Lua::pushString(L, description); } else { lua_pushnil(L); } @@ -283,7 +353,7 @@ int ItemTypeFunctions::luaItemTypeGetDescription(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetSlotPosition(lua_State* L) { // itemType:getSlotPosition() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->slotPosition); } else { @@ -294,7 +364,7 @@ int ItemTypeFunctions::luaItemTypeGetSlotPosition(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetCharges(lua_State* L) { // itemType:getCharges() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->charges); } else { @@ -305,7 +375,7 @@ int ItemTypeFunctions::luaItemTypeGetCharges(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetFluidSource(lua_State* L) { // itemType:getFluidSource() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->fluidSource); } else { @@ -316,7 +386,7 @@ int ItemTypeFunctions::luaItemTypeGetFluidSource(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetCapacity(lua_State* L) { // itemType:getCapacity() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->maxItems); } else { @@ -327,35 +397,35 @@ int ItemTypeFunctions::luaItemTypeGetCapacity(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetWeight(lua_State* L) { // itemType:getWeight([count = 1]) - uint16_t count = getNumber<uint16_t>(L, 2, 1); + const auto count = Lua::getNumber<uint16_t>(L, 2, 1); - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; } - uint64_t weight = static_cast<uint64_t>(itemType->weight) * std::max<int32_t>(1, count); + const uint64_t weight = static_cast<uint64_t>(itemType->weight) * std::max<int32_t>(1, count); lua_pushnumber(L, weight); return 1; } int ItemTypeFunctions::luaItemTypeGetStackSize(lua_State* L) { // itemType:getStackSize() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; } - uint64_t stackSize = static_cast<uint64_t>(itemType->stackSize); + const auto stackSize = static_cast<uint64_t>(itemType->stackSize); lua_pushnumber(L, stackSize); return 1; } int ItemTypeFunctions::luaItemTypeGetHitChance(lua_State* L) { // itemType:getHitChance() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->hitChance); } else { @@ -366,7 +436,7 @@ int ItemTypeFunctions::luaItemTypeGetHitChance(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetShootRange(lua_State* L) { // itemType:getShootRange() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->shootRange); } else { @@ -377,7 +447,7 @@ int ItemTypeFunctions::luaItemTypeGetShootRange(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetAttack(lua_State* L) { // itemType:getAttack() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->attack); } else { @@ -388,7 +458,7 @@ int ItemTypeFunctions::luaItemTypeGetAttack(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetDefense(lua_State* L) { // itemType:getDefense() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->defense); } else { @@ -399,7 +469,7 @@ int ItemTypeFunctions::luaItemTypeGetDefense(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetExtraDefense(lua_State* L) { // itemType:getExtraDefense() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->extraDefense); } else { @@ -410,7 +480,7 @@ int ItemTypeFunctions::luaItemTypeGetExtraDefense(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetImbuementSlot(lua_State* L) { // itemType:getImbuementSlot() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->imbuementSlot); } else { @@ -421,7 +491,7 @@ int ItemTypeFunctions::luaItemTypeGetImbuementSlot(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetArmor(lua_State* L) { // itemType:getArmor() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->armor); } else { @@ -432,7 +502,7 @@ int ItemTypeFunctions::luaItemTypeGetArmor(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetWeaponType(lua_State* L) { // itemType:getWeaponType() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->weaponType); } else { @@ -443,7 +513,7 @@ int ItemTypeFunctions::luaItemTypeGetWeaponType(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetAmmoType(lua_State* L) { // itemType:getAmmoType() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->ammoType); } else { @@ -454,7 +524,7 @@ int ItemTypeFunctions::luaItemTypeGetAmmoType(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetElementType(lua_State* L) { // itemType:getElementType() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; @@ -471,7 +541,7 @@ int ItemTypeFunctions::luaItemTypeGetElementType(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetElementDamage(lua_State* L) { // itemType:getElementDamage() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; @@ -488,7 +558,7 @@ int ItemTypeFunctions::luaItemTypeGetElementDamage(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetTransformEquipId(lua_State* L) { // itemType:getTransformEquipId() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->transformEquipTo); } else { @@ -499,7 +569,7 @@ int ItemTypeFunctions::luaItemTypeGetTransformEquipId(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetTransformDeEquipId(lua_State* L) { // itemType:getTransformDeEquipId() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->transformDeEquipTo); } else { @@ -510,7 +580,7 @@ int ItemTypeFunctions::luaItemTypeGetTransformDeEquipId(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetDestroyId(lua_State* L) { // itemType:getDestroyId() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->destroyTo); } else { @@ -521,7 +591,7 @@ int ItemTypeFunctions::luaItemTypeGetDestroyId(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetDecayId(lua_State* L) { // itemType:getDecayId() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->decayTo); } else { @@ -532,7 +602,7 @@ int ItemTypeFunctions::luaItemTypeGetDecayId(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetRequiredLevel(lua_State* L) { // itemType:getRequiredLevel() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->minReqLevel); } else { @@ -543,7 +613,7 @@ int ItemTypeFunctions::luaItemTypeGetRequiredLevel(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetSpeed(lua_State* L) { // itemType:getSpeed() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (!itemType) { lua_pushnil(L); return 1; @@ -560,7 +630,7 @@ int ItemTypeFunctions::luaItemTypeGetSpeed(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetBaseSpeed(lua_State* L) { // itemType:getBaseSpeed() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->speed); } else { @@ -571,7 +641,7 @@ int ItemTypeFunctions::luaItemTypeGetBaseSpeed(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetDecayTime(lua_State* L) { // itemType:getDecayTime() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->decayTime); } else { @@ -582,7 +652,7 @@ int ItemTypeFunctions::luaItemTypeGetDecayTime(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetShowDuration(lua_State* L) { // itemType:getShowDuration() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushboolean(L, itemType->showDuration); } else { @@ -592,7 +662,7 @@ int ItemTypeFunctions::luaItemTypeGetShowDuration(lua_State* L) { } int ItemTypeFunctions::luaItemTypeGetWrapableTo(lua_State* L) { // itemType:getWrapableTo() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { lua_pushnumber(L, itemType->wrapableTo); } else { @@ -603,9 +673,9 @@ int ItemTypeFunctions::luaItemTypeGetWrapableTo(lua_State* L) { int ItemTypeFunctions::luaItemTypeHasSubType(lua_State* L) { // itemType:hasSubType() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushBoolean(L, itemType->hasSubType()); + Lua::pushBoolean(L, itemType->hasSubType()); } else { lua_pushnil(L); } @@ -614,9 +684,9 @@ int ItemTypeFunctions::luaItemTypeHasSubType(lua_State* L) { int ItemTypeFunctions::luaItemTypeGetVocationString(lua_State* L) { // itemType:getVocationString() - const ItemType* itemType = getUserdata<const ItemType>(L, 1); + const auto* itemType = Lua::getUserdata<const ItemType>(L, 1); if (itemType) { - pushString(L, itemType->vocationString); + Lua::pushString(L, itemType->vocationString); } else { lua_pushnil(L); } diff --git a/src/lua/functions/items/item_type_functions.hpp b/src/lua/functions/items/item_type_functions.hpp index ce53d429804..19a401bc235 100644 --- a/src/lua/functions/items/item_type_functions.hpp +++ b/src/lua/functions/items/item_type_functions.hpp @@ -9,78 +9,11 @@ #pragma once -#include "lua/scripts/luascript.hpp" #include "lua/functions/items/item_classification_functions.hpp" -class ItemTypeFunctions final : LuaScriptInterface { +class ItemTypeFunctions { public: - static void init(lua_State* L) { - registerClass(L, "ItemType", "", ItemTypeFunctions::luaItemTypeCreate); - registerMetaMethod(L, "ItemType", "__eq", ItemTypeFunctions::luaUserdataCompare); - - registerMethod(L, "ItemType", "isCorpse", ItemTypeFunctions::luaItemTypeIsCorpse); - registerMethod(L, "ItemType", "isDoor", ItemTypeFunctions::luaItemTypeIsDoor); - registerMethod(L, "ItemType", "isContainer", ItemTypeFunctions::luaItemTypeIsContainer); - registerMethod(L, "ItemType", "isFluidContainer", ItemTypeFunctions::luaItemTypeIsFluidContainer); - registerMethod(L, "ItemType", "isMovable", ItemTypeFunctions::luaItemTypeIsMovable); - registerMethod(L, "ItemType", "isRune", ItemTypeFunctions::luaItemTypeIsRune); - registerMethod(L, "ItemType", "isStackable", ItemTypeFunctions::luaItemTypeIsStackable); - registerMethod(L, "ItemType", "isStowable", ItemTypeFunctions::luaItemTypeIsStowable); - registerMethod(L, "ItemType", "isReadable", ItemTypeFunctions::luaItemTypeIsReadable); - registerMethod(L, "ItemType", "isWritable", ItemTypeFunctions::luaItemTypeIsWritable); - registerMethod(L, "ItemType", "isBlocking", ItemTypeFunctions::luaItemTypeIsBlocking); - registerMethod(L, "ItemType", "isGroundTile", ItemTypeFunctions::luaItemTypeIsGroundTile); - registerMethod(L, "ItemType", "isMagicField", ItemTypeFunctions::luaItemTypeIsMagicField); - registerMethod(L, "ItemType", "isMultiUse", ItemTypeFunctions::luaItemTypeIsMultiUse); - registerMethod(L, "ItemType", "isPickupable", ItemTypeFunctions::luaItemTypeIsPickupable); - registerMethod(L, "ItemType", "isKey", ItemTypeFunctions::luaItemTypeIsKey); - registerMethod(L, "ItemType", "isQuiver", ItemTypeFunctions::luaItemTypeIsQuiver); - - registerMethod(L, "ItemType", "getType", ItemTypeFunctions::luaItemTypeGetType); - registerMethod(L, "ItemType", "getId", ItemTypeFunctions::luaItemTypeGetId); - registerMethod(L, "ItemType", "getName", ItemTypeFunctions::luaItemTypeGetName); - registerMethod(L, "ItemType", "getPluralName", ItemTypeFunctions::luaItemTypeGetPluralName); - registerMethod(L, "ItemType", "getArticle", ItemTypeFunctions::luaItemTypeGetArticle); - registerMethod(L, "ItemType", "getDescription", ItemTypeFunctions::luaItemTypeGetDescription); - registerMethod(L, "ItemType", "getSlotPosition", ItemTypeFunctions::luaItemTypeGetSlotPosition); - - registerMethod(L, "ItemType", "getCharges", ItemTypeFunctions::luaItemTypeGetCharges); - registerMethod(L, "ItemType", "getFluidSource", ItemTypeFunctions::luaItemTypeGetFluidSource); - registerMethod(L, "ItemType", "getCapacity", ItemTypeFunctions::luaItemTypeGetCapacity); - registerMethod(L, "ItemType", "getWeight", ItemTypeFunctions::luaItemTypeGetWeight); - registerMethod(L, "ItemType", "getStackSize", ItemTypeFunctions::luaItemTypeGetStackSize); - - registerMethod(L, "ItemType", "getHitChance", ItemTypeFunctions::luaItemTypeGetHitChance); - registerMethod(L, "ItemType", "getShootRange", ItemTypeFunctions::luaItemTypeGetShootRange); - - registerMethod(L, "ItemType", "getAttack", ItemTypeFunctions::luaItemTypeGetAttack); - registerMethod(L, "ItemType", "getDefense", ItemTypeFunctions::luaItemTypeGetDefense); - registerMethod(L, "ItemType", "getExtraDefense", ItemTypeFunctions::luaItemTypeGetExtraDefense); - registerMethod(L, "ItemType", "getImbuementSlot", ItemTypeFunctions::luaItemTypeGetImbuementSlot); - registerMethod(L, "ItemType", "getArmor", ItemTypeFunctions::luaItemTypeGetArmor); - registerMethod(L, "ItemType", "getWeaponType", ItemTypeFunctions::luaItemTypeGetWeaponType); - - registerMethod(L, "ItemType", "getElementType", ItemTypeFunctions::luaItemTypeGetElementType); - registerMethod(L, "ItemType", "getElementDamage", ItemTypeFunctions::luaItemTypeGetElementDamage); - - registerMethod(L, "ItemType", "getTransformEquipId", ItemTypeFunctions::luaItemTypeGetTransformEquipId); - registerMethod(L, "ItemType", "getTransformDeEquipId", ItemTypeFunctions::luaItemTypeGetTransformDeEquipId); - registerMethod(L, "ItemType", "getDestroyId", ItemTypeFunctions::luaItemTypeGetDestroyId); - registerMethod(L, "ItemType", "getDecayId", ItemTypeFunctions::luaItemTypeGetDecayId); - registerMethod(L, "ItemType", "getRequiredLevel", ItemTypeFunctions::luaItemTypeGetRequiredLevel); - registerMethod(L, "ItemType", "getAmmoType", ItemTypeFunctions::luaItemTypeGetAmmoType); - - registerMethod(L, "ItemType", "getDecayTime", ItemTypeFunctions::luaItemTypeGetDecayTime); - registerMethod(L, "ItemType", "getShowDuration", ItemTypeFunctions::luaItemTypeGetShowDuration); - registerMethod(L, "ItemType", "getWrapableTo", ItemTypeFunctions::luaItemTypeGetWrapableTo); - registerMethod(L, "ItemType", "getSpeed", ItemTypeFunctions::luaItemTypeGetSpeed); - registerMethod(L, "ItemType", "getBaseSpeed", ItemTypeFunctions::luaItemTypeGetBaseSpeed); - registerMethod(L, "ItemType", "getVocationString", ItemTypeFunctions::luaItemTypeGetVocationString); - - registerMethod(L, "ItemType", "hasSubType", ItemTypeFunctions::luaItemTypeHasSubType); - - ItemClassificationFunctions::init(L); - } + static void init(lua_State* L); private: static int luaItemTypeCreate(lua_State* L); diff --git a/src/lua/functions/items/weapon_functions.cpp b/src/lua/functions/items/weapon_functions.cpp index cd0acf94849..e87d843116a 100644 --- a/src/lua/functions/items/weapon_functions.cpp +++ b/src/lua/functions/items/weapon_functions.cpp @@ -12,45 +12,77 @@ #include "game/game.hpp" #include "items/item.hpp" #include "lua/scripts/lua_environment.hpp" -#include "lua/scripts/scripts.hpp" #include "utils/tools.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void WeaponFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Weapon", "", WeaponFunctions::luaCreateWeapon); + Lua::registerMethod(L, "Weapon", "action", WeaponFunctions::luaWeaponAction); + Lua::registerMethod(L, "Weapon", "register", WeaponFunctions::luaWeaponRegister); + Lua::registerMethod(L, "Weapon", "id", WeaponFunctions::luaWeaponId); + Lua::registerMethod(L, "Weapon", "level", WeaponFunctions::luaWeaponLevel); + Lua::registerMethod(L, "Weapon", "magicLevel", WeaponFunctions::luaWeaponMagicLevel); + Lua::registerMethod(L, "Weapon", "mana", WeaponFunctions::luaWeaponMana); + Lua::registerMethod(L, "Weapon", "manaPercent", WeaponFunctions::luaWeaponManaPercent); + Lua::registerMethod(L, "Weapon", "health", WeaponFunctions::luaWeaponHealth); + Lua::registerMethod(L, "Weapon", "healthPercent", WeaponFunctions::luaWeaponHealthPercent); + Lua::registerMethod(L, "Weapon", "soul", WeaponFunctions::luaWeaponSoul); + Lua::registerMethod(L, "Weapon", "breakChance", WeaponFunctions::luaWeaponBreakChance); + Lua::registerMethod(L, "Weapon", "premium", WeaponFunctions::luaWeaponPremium); + Lua::registerMethod(L, "Weapon", "wieldUnproperly", WeaponFunctions::luaWeaponUnproperly); + Lua::registerMethod(L, "Weapon", "vocation", WeaponFunctions::luaWeaponVocation); + Lua::registerMethod(L, "Weapon", "onUseWeapon", WeaponFunctions::luaWeaponOnUseWeapon); + Lua::registerMethod(L, "Weapon", "element", WeaponFunctions::luaWeaponElement); + Lua::registerMethod(L, "Weapon", "attack", WeaponFunctions::luaWeaponAttack); + Lua::registerMethod(L, "Weapon", "defense", WeaponFunctions::luaWeaponDefense); + Lua::registerMethod(L, "Weapon", "range", WeaponFunctions::luaWeaponRange); + Lua::registerMethod(L, "Weapon", "charges", WeaponFunctions::luaWeaponCharges); + Lua::registerMethod(L, "Weapon", "duration", WeaponFunctions::luaWeaponDuration); + Lua::registerMethod(L, "Weapon", "decayTo", WeaponFunctions::luaWeaponDecayTo); + Lua::registerMethod(L, "Weapon", "transformEquipTo", WeaponFunctions::luaWeaponTransformEquipTo); + Lua::registerMethod(L, "Weapon", "transformDeEquipTo", WeaponFunctions::luaWeaponTransformDeEquipTo); + Lua::registerMethod(L, "Weapon", "slotType", WeaponFunctions::luaWeaponSlotType); + Lua::registerMethod(L, "Weapon", "hitChance", WeaponFunctions::luaWeaponHitChance); + Lua::registerMethod(L, "Weapon", "extraElement", WeaponFunctions::luaWeaponExtraElement); + + // exclusively for distance weapons + Lua::registerMethod(L, "Weapon", "ammoType", WeaponFunctions::luaWeaponAmmoType); + Lua::registerMethod(L, "Weapon", "maxHitChance", WeaponFunctions::luaWeaponMaxHitChance); + + // exclusively for wands + Lua::registerMethod(L, "Weapon", "damage", WeaponFunctions::luaWeaponWandDamage); + + // exclusively for wands & distance weapons + Lua::registerMethod(L, "Weapon", "shootType", WeaponFunctions::luaWeaponShootType); +} int WeaponFunctions::luaCreateWeapon(lua_State* L) { // Weapon(type) - WeaponType_t type = getNumber<WeaponType_t>(L, 2); + const WeaponType_t type = Lua::getNumber<WeaponType_t>(L, 2); switch (type) { case WEAPON_SWORD: case WEAPON_AXE: case WEAPON_CLUB: { - if (auto weaponPtr = g_luaEnvironment().createWeaponObject<WeaponMelee>(getScriptEnv()->getScriptInterface())) { - pushUserdata<WeaponMelee>(L, weaponPtr); - setMetatable(L, -1, "Weapon"); - weaponPtr->weaponType = type; - } else { - lua_pushnil(L); - } + auto weaponPtr = std::make_shared<WeaponMelee>(); + Lua::pushUserdata<WeaponMelee>(L, weaponPtr); + Lua::setMetatable(L, -1, "Weapon"); + weaponPtr->weaponType = type; break; } case WEAPON_MISSILE: case WEAPON_DISTANCE: case WEAPON_AMMO: { - if (auto weaponPtr = g_luaEnvironment().createWeaponObject<WeaponDistance>(getScriptEnv()->getScriptInterface())) { - pushUserdata<WeaponDistance>(L, weaponPtr); - setMetatable(L, -1, "Weapon"); - weaponPtr->weaponType = type; - } else { - lua_pushnil(L); - } + auto weaponPtr = std::make_shared<WeaponDistance>(); + Lua::pushUserdata<WeaponDistance>(L, weaponPtr); + Lua::setMetatable(L, -1, "Weapon"); + weaponPtr->weaponType = type; break; } case WEAPON_WAND: { - if (auto weaponPtr = g_luaEnvironment().createWeaponObject<WeaponWand>(getScriptEnv()->getScriptInterface())) { - pushUserdata<WeaponWand>(L, weaponPtr); - setMetatable(L, -1, "Weapon"); - weaponPtr->weaponType = type; - } else { - lua_pushnil(L); - } + auto weaponPtr = std::make_shared<WeaponWand>(); + Lua::pushUserdata<WeaponWand>(L, weaponPtr); + Lua::setMetatable(L, -1, "Weapon"); + weaponPtr->weaponType = type; break; } default: { @@ -63,10 +95,10 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) { int WeaponFunctions::luaWeaponAction(lua_State* L) { // weapon:action(callback) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - std::string typeName = getString(L, 2); - std::string tmpStr = asLowerCaseString(typeName); + std::string typeName = Lua::getString(L, 2); + const std::string tmpStr = asLowerCaseString(typeName); if (tmpStr == "removecount") { weapon->action = WEAPONACTION_REMOVECOUNT; } else if (tmpStr == "removecharge") { @@ -77,9 +109,9 @@ int WeaponFunctions::luaWeaponAction(lua_State* L) { g_logger().error("[WeaponFunctions::luaWeaponAction] - " "No valid action {}", typeName); - pushBoolean(L, false); + Lua::pushBoolean(L, false); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -88,18 +120,18 @@ int WeaponFunctions::luaWeaponAction(lua_State* L) { int WeaponFunctions::luaWeaponRegister(lua_State* L) { // weapon:register() - WeaponShared_ptr* weaponPtr = getRawUserDataShared<Weapon>(L, 1); + const WeaponShared_ptr* weaponPtr = Lua::getRawUserDataShared<Weapon>(L, 1); if (weaponPtr && *weaponPtr) { WeaponShared_ptr weapon = *weaponPtr; if (weapon->weaponType == WEAPON_DISTANCE || weapon->weaponType == WEAPON_AMMO || weapon->weaponType == WEAPON_MISSILE) { - weapon = getUserdataShared<WeaponDistance>(L, 1); + weapon = Lua::getUserdataShared<WeaponDistance>(L, 1); } else if (weapon->weaponType == WEAPON_WAND) { - weapon = getUserdataShared<WeaponWand>(L, 1); + weapon = Lua::getUserdataShared<WeaponWand>(L, 1); } else { - weapon = getUserdataShared<WeaponMelee>(L, 1); + weapon = Lua::getUserdataShared<WeaponMelee>(L, 1); } - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); it.weaponType = weapon->weaponType; @@ -111,7 +143,7 @@ int WeaponFunctions::luaWeaponRegister(lua_State* L) { } weapon->configureWeapon(it); - pushBoolean(L, g_weapons().registerLuaEvent(weapon)); + Lua::pushBoolean(L, g_weapons().registerLuaEvent(weapon)); weapon = nullptr; // Releases weapon, removing the luascript reference } else { lua_pushnil(L); @@ -121,14 +153,14 @@ int WeaponFunctions::luaWeaponRegister(lua_State* L) { int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) { // weapon:onUseWeapon(callback) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - if (!weapon->loadCallback()) { - pushBoolean(L, false); + if (!weapon->loadScriptId()) { + Lua::pushBoolean(L, false); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -137,10 +169,10 @@ int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) { int WeaponFunctions::luaWeaponUnproperly(lua_State* L) { // weapon:wieldedUnproperly(bool) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setWieldUnproperly(getBoolean(L, 2)); - pushBoolean(L, true); + weapon->setWieldUnproperly(Lua::getBoolean(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -149,11 +181,11 @@ int WeaponFunctions::luaWeaponUnproperly(lua_State* L) { int WeaponFunctions::luaWeaponLevel(lua_State* L) { // weapon:level(lvl) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setRequiredLevel(getNumber<uint32_t>(L, 2)); + weapon->setRequiredLevel(Lua::getNumber<uint32_t>(L, 2)); weapon->setWieldInfo(WIELDINFO_LEVEL); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -162,11 +194,11 @@ int WeaponFunctions::luaWeaponLevel(lua_State* L) { int WeaponFunctions::luaWeaponMagicLevel(lua_State* L) { // weapon:magicLevel(lvl) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setRequiredMagLevel(getNumber<uint32_t>(L, 2)); + weapon->setRequiredMagLevel(Lua::getNumber<uint32_t>(L, 2)); weapon->setWieldInfo(WIELDINFO_MAGLV); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -175,10 +207,10 @@ int WeaponFunctions::luaWeaponMagicLevel(lua_State* L) { int WeaponFunctions::luaWeaponMana(lua_State* L) { // weapon:mana(mana) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setMana(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + weapon->setMana(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -187,10 +219,10 @@ int WeaponFunctions::luaWeaponMana(lua_State* L) { int WeaponFunctions::luaWeaponManaPercent(lua_State* L) { // weapon:manaPercent(percent) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setManaPercent(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + weapon->setManaPercent(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -199,10 +231,10 @@ int WeaponFunctions::luaWeaponManaPercent(lua_State* L) { int WeaponFunctions::luaWeaponHealth(lua_State* L) { // weapon:health(health) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setHealth(getNumber<int32_t>(L, 2)); - pushBoolean(L, true); + weapon->setHealth(Lua::getNumber<int32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -211,10 +243,10 @@ int WeaponFunctions::luaWeaponHealth(lua_State* L) { int WeaponFunctions::luaWeaponHealthPercent(lua_State* L) { // weapon:healthPercent(percent) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setHealthPercent(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + weapon->setHealthPercent(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -223,10 +255,10 @@ int WeaponFunctions::luaWeaponHealthPercent(lua_State* L) { int WeaponFunctions::luaWeaponSoul(lua_State* L) { // weapon:soul(soul) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setSoul(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + weapon->setSoul(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -235,10 +267,10 @@ int WeaponFunctions::luaWeaponSoul(lua_State* L) { int WeaponFunctions::luaWeaponBreakChance(lua_State* L) { // weapon:breakChance(percent) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setBreakChance(getNumber<uint32_t>(L, 2)); - pushBoolean(L, true); + weapon->setBreakChance(Lua::getNumber<uint32_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -247,15 +279,15 @@ 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! - const auto &weapon = getUserdataShared<WeaponWand>(L, 1); + const auto &weapon = Lua::getUserdataShared<WeaponWand>(L, 1); if (weapon) { - weapon->setMinChange(getNumber<uint32_t>(L, 2)); + weapon->setMinChange(Lua::getNumber<uint32_t>(L, 2)); if (lua_gettop(L) > 2) { - weapon->setMaxChange(getNumber<uint32_t>(L, 3)); + weapon->setMaxChange(Lua::getNumber<uint32_t>(L, 3)); } else { - weapon->setMaxChange(getNumber<uint32_t>(L, 2)); + weapon->setMaxChange(Lua::getNumber<uint32_t>(L, 2)); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -264,11 +296,11 @@ int WeaponFunctions::luaWeaponWandDamage(lua_State* L) { int WeaponFunctions::luaWeaponElement(lua_State* L) { // weapon:element(combatType) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - if (!getNumber<CombatType_t>(L, 2)) { - std::string element = getString(L, 2); - std::string tmpStrValue = asLowerCaseString(element); + if (!Lua::getNumber<CombatType_t>(L, 2)) { + std::string element = Lua::getString(L, 2); + const std::string tmpStrValue = asLowerCaseString(element); if (tmpStrValue == "earth") { weapon->params.combatType = COMBAT_EARTHDAMAGE; } else if (tmpStrValue == "ice") { @@ -287,9 +319,9 @@ int WeaponFunctions::luaWeaponElement(lua_State* L) { element); } } else { - weapon->params.combatType = getNumber<CombatType_t>(L, 2); + weapon->params.combatType = Lua::getNumber<CombatType_t>(L, 2); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -298,11 +330,11 @@ int WeaponFunctions::luaWeaponElement(lua_State* L) { int WeaponFunctions::luaWeaponPremium(lua_State* L) { // weapon:premium(bool) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setNeedPremium(getBoolean(L, 2)); + weapon->setNeedPremium(Lua::getBoolean(L, 2)); weapon->setWieldInfo(WIELDINFO_PREMIUM); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -311,22 +343,22 @@ int WeaponFunctions::luaWeaponPremium(lua_State* L) { int WeaponFunctions::luaWeaponVocation(lua_State* L) { // weapon:vocation(vocName[, showInDescription = false, lastVoc = false]) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->addVocWeaponMap(getString(L, 2)); + weapon->addVocWeaponMap(Lua::getString(L, 2)); weapon->setWieldInfo(WIELDINFO_VOCREQ); std::string tmp; bool showInDescription = false; bool lastVoc = false; - if (getBoolean(L, 3)) { - showInDescription = getBoolean(L, 3); + if (Lua::getBoolean(L, 3)) { + showInDescription = Lua::getBoolean(L, 3); } - if (getBoolean(L, 4)) { - lastVoc = getBoolean(L, 4); + if (Lua::getBoolean(L, 4)) { + lastVoc = Lua::getBoolean(L, 4); } if (showInDescription) { if (weapon->getVocationString().empty()) { - tmp = asLowerCaseString(getString(L, 2)); + tmp = asLowerCaseString(Lua::getString(L, 2)); tmp += "s"; weapon->setVocationString(tmp); } else { @@ -336,12 +368,12 @@ int WeaponFunctions::luaWeaponVocation(lua_State* L) { } else { tmp += ", "; } - tmp += asLowerCaseString(getString(L, 2)); + tmp += asLowerCaseString(Lua::getString(L, 2)); tmp += "s"; weapon->setVocationString(tmp); } } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -350,10 +382,10 @@ int WeaponFunctions::luaWeaponVocation(lua_State* L) { int WeaponFunctions::luaWeaponId(lua_State* L) { // weapon:id(id) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - weapon->setID(getNumber<uint16_t>(L, 2)); - pushBoolean(L, true); + weapon->setID(Lua::getNumber<uint16_t>(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -362,12 +394,12 @@ int WeaponFunctions::luaWeaponId(lua_State* L) { int WeaponFunctions::luaWeaponAttack(lua_State* L) { // weapon:attack(atk) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.attack = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + it.attack = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -376,15 +408,15 @@ int WeaponFunctions::luaWeaponAttack(lua_State* L) { int WeaponFunctions::luaWeaponDefense(lua_State* L) { // weapon:defense(defense[, extraDefense]) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.defense = getNumber<int32_t>(L, 2); + it.defense = Lua::getNumber<int32_t>(L, 2); if (lua_gettop(L) > 2) { - it.extraDefense = getNumber<int32_t>(L, 3); + it.extraDefense = Lua::getNumber<int32_t>(L, 3); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -393,12 +425,12 @@ int WeaponFunctions::luaWeaponDefense(lua_State* L) { int WeaponFunctions::luaWeaponRange(lua_State* L) { // weapon:range(range) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.shootRange = getNumber<uint8_t>(L, 2); - pushBoolean(L, true); + it.shootRange = Lua::getNumber<uint8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -407,17 +439,17 @@ int WeaponFunctions::luaWeaponRange(lua_State* L) { int WeaponFunctions::luaWeaponCharges(lua_State* L) { // weapon:charges(charges[, showCharges = true]) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { bool showCharges = true; if (lua_gettop(L) > 2) { - showCharges = getBoolean(L, 3); + showCharges = Lua::getBoolean(L, 3); } - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.charges = getNumber<uint8_t>(L, 2); + it.charges = Lua::getNumber<uint8_t>(L, 2); it.showCharges = showCharges; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -426,17 +458,17 @@ int WeaponFunctions::luaWeaponCharges(lua_State* L) { int WeaponFunctions::luaWeaponDuration(lua_State* L) { // weapon:duration(duration[, showDuration = true]) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { bool showDuration = true; if (lua_gettop(L) > 2) { - showDuration = getBoolean(L, 3); + showDuration = Lua::getBoolean(L, 3); } - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.decayTime = getNumber<uint8_t>(L, 2); + it.decayTime = Lua::getNumber<uint8_t>(L, 2); it.showDuration = showDuration; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -445,16 +477,16 @@ int WeaponFunctions::luaWeaponDuration(lua_State* L) { int WeaponFunctions::luaWeaponDecayTo(lua_State* L) { // weapon:decayTo([itemid = 0] - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { uint16_t itemid = 0; if (lua_gettop(L) > 1) { - itemid = getNumber<uint16_t>(L, 2); + itemid = Lua::getNumber<uint16_t>(L, 2); } - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); it.decayTo = itemid; - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -463,12 +495,12 @@ int WeaponFunctions::luaWeaponDecayTo(lua_State* L) { int WeaponFunctions::luaWeaponTransformEquipTo(lua_State* L) { // weapon:transformEquipTo(itemid) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.transformEquipTo = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + it.transformEquipTo = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -477,12 +509,12 @@ int WeaponFunctions::luaWeaponTransformEquipTo(lua_State* L) { int WeaponFunctions::luaWeaponTransformDeEquipTo(lua_State* L) { // weapon:transformDeEquipTo(itemid) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.transformDeEquipTo = getNumber<uint16_t>(L, 2); - pushBoolean(L, true); + it.transformDeEquipTo = Lua::getNumber<uint16_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -491,12 +523,12 @@ int WeaponFunctions::luaWeaponTransformDeEquipTo(lua_State* L) { int WeaponFunctions::luaWeaponShootType(lua_State* L) { // weapon:shootType(type) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.shootType = getNumber<ShootType_t>(L, 2); - pushBoolean(L, true); + it.shootType = Lua::getNumber<ShootType_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -505,18 +537,18 @@ int WeaponFunctions::luaWeaponShootType(lua_State* L) { int WeaponFunctions::luaWeaponSlotType(lua_State* L) { // weapon:slotType(slot) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - std::string slot = getString(L, 2); + const std::string slot = Lua::getString(L, 2); if (slot == "two-handed") { it.slotPosition = SLOTP_TWO_HAND; } else { it.slotPosition = SLOTP_HAND; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -525,11 +557,11 @@ int WeaponFunctions::luaWeaponSlotType(lua_State* L) { int WeaponFunctions::luaWeaponAmmoType(lua_State* L) { // weapon:ammoType(type) - const auto &weapon = getUserdataShared<WeaponDistance>(L, 1); + const auto &weapon = Lua::getUserdataShared<WeaponDistance>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - std::string type = getString(L, 2); + std::string type = Lua::getString(L, 2); if (type == "arrow") { it.ammoType = AMMO_ARROW; @@ -542,7 +574,7 @@ int WeaponFunctions::luaWeaponAmmoType(lua_State* L) { lua_pushnil(L); return 1; } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -551,12 +583,12 @@ int WeaponFunctions::luaWeaponAmmoType(lua_State* L) { int WeaponFunctions::luaWeaponHitChance(lua_State* L) { // weapon:hitChance(chance) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.hitChance = getNumber<int8_t>(L, 2); - pushBoolean(L, true); + it.hitChance = Lua::getNumber<int8_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -565,12 +597,12 @@ int WeaponFunctions::luaWeaponHitChance(lua_State* L) { int WeaponFunctions::luaWeaponMaxHitChance(lua_State* L) { // weapon:maxHitChance(max) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); + const uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.maxHitChance = getNumber<int32_t>(L, 2); - pushBoolean(L, true); + it.maxHitChance = Lua::getNumber<int32_t>(L, 2); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -579,15 +611,15 @@ int WeaponFunctions::luaWeaponMaxHitChance(lua_State* L) { int WeaponFunctions::luaWeaponExtraElement(lua_State* L) { // weapon:extraElement(atk, combatType) - const WeaponShared_ptr &weapon = getUserdataShared<Weapon>(L, 1); + const WeaponShared_ptr &weapon = Lua::getUserdataShared<Weapon>(L, 1); if (weapon) { - uint16_t id = weapon->getID(); - ItemType &it = Item::items.getItemType(id); - it.abilities->elementDamage = getNumber<uint16_t>(L, 2); + const uint16_t id = weapon->getID(); + const ItemType &it = Item::items.getItemType(id); + it.abilities->elementDamage = Lua::getNumber<uint16_t>(L, 2); - if (!getNumber<CombatType_t>(L, 3)) { - std::string element = getString(L, 3); - std::string tmpStrValue = asLowerCaseString(element); + if (!Lua::getNumber<CombatType_t>(L, 3)) { + std::string element = Lua::getString(L, 3); + const std::string tmpStrValue = asLowerCaseString(element); if (tmpStrValue == "earth") { it.abilities->elementType = COMBAT_EARTHDAMAGE; } else if (tmpStrValue == "ice") { @@ -606,9 +638,9 @@ int WeaponFunctions::luaWeaponExtraElement(lua_State* L) { element); } } else { - it.abilities->elementType = getNumber<CombatType_t>(L, 3); + it.abilities->elementType = Lua::getNumber<CombatType_t>(L, 3); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/items/weapon_functions.hpp b/src/lua/functions/items/weapon_functions.hpp index b7ac6fe6aaa..971ff286036 100644 --- a/src/lua/functions/items/weapon_functions.hpp +++ b/src/lua/functions/items/weapon_functions.hpp @@ -9,50 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class WeaponFunctions final : LuaScriptInterface { +class WeaponFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Weapon", "", WeaponFunctions::luaCreateWeapon); - registerMethod(L, "Weapon", "action", WeaponFunctions::luaWeaponAction); - registerMethod(L, "Weapon", "register", WeaponFunctions::luaWeaponRegister); - registerMethod(L, "Weapon", "id", WeaponFunctions::luaWeaponId); - registerMethod(L, "Weapon", "level", WeaponFunctions::luaWeaponLevel); - registerMethod(L, "Weapon", "magicLevel", WeaponFunctions::luaWeaponMagicLevel); - registerMethod(L, "Weapon", "mana", WeaponFunctions::luaWeaponMana); - registerMethod(L, "Weapon", "manaPercent", WeaponFunctions::luaWeaponManaPercent); - registerMethod(L, "Weapon", "health", WeaponFunctions::luaWeaponHealth); - registerMethod(L, "Weapon", "healthPercent", WeaponFunctions::luaWeaponHealthPercent); - registerMethod(L, "Weapon", "soul", WeaponFunctions::luaWeaponSoul); - registerMethod(L, "Weapon", "breakChance", WeaponFunctions::luaWeaponBreakChance); - registerMethod(L, "Weapon", "premium", WeaponFunctions::luaWeaponPremium); - registerMethod(L, "Weapon", "wieldUnproperly", WeaponFunctions::luaWeaponUnproperly); - registerMethod(L, "Weapon", "vocation", WeaponFunctions::luaWeaponVocation); - registerMethod(L, "Weapon", "onUseWeapon", WeaponFunctions::luaWeaponOnUseWeapon); - registerMethod(L, "Weapon", "element", WeaponFunctions::luaWeaponElement); - registerMethod(L, "Weapon", "attack", WeaponFunctions::luaWeaponAttack); - registerMethod(L, "Weapon", "defense", WeaponFunctions::luaWeaponDefense); - registerMethod(L, "Weapon", "range", WeaponFunctions::luaWeaponRange); - registerMethod(L, "Weapon", "charges", WeaponFunctions::luaWeaponCharges); - registerMethod(L, "Weapon", "duration", WeaponFunctions::luaWeaponDuration); - registerMethod(L, "Weapon", "decayTo", WeaponFunctions::luaWeaponDecayTo); - registerMethod(L, "Weapon", "transformEquipTo", WeaponFunctions::luaWeaponTransformEquipTo); - registerMethod(L, "Weapon", "transformDeEquipTo", WeaponFunctions::luaWeaponTransformDeEquipTo); - registerMethod(L, "Weapon", "slotType", WeaponFunctions::luaWeaponSlotType); - registerMethod(L, "Weapon", "hitChance", WeaponFunctions::luaWeaponHitChance); - registerMethod(L, "Weapon", "extraElement", WeaponFunctions::luaWeaponExtraElement); - - // exclusively for distance weapons - registerMethod(L, "Weapon", "ammoType", WeaponFunctions::luaWeaponAmmoType); - registerMethod(L, "Weapon", "maxHitChance", WeaponFunctions::luaWeaponMaxHitChance); - - // exclusively for wands - registerMethod(L, "Weapon", "damage", WeaponFunctions::luaWeaponWandDamage); - - // exclusively for wands & distance weapons - registerMethod(L, "Weapon", "shootType", WeaponFunctions::luaWeaponShootType); - } + static void init(lua_State* L); private: static int luaCreateWeapon(lua_State* L); diff --git a/src/lua/functions/lua_functions_loader.cpp b/src/lua/functions/lua_functions_loader.cpp index ad52431a661..d4aeac2a7f1 100644 --- a/src/lua/functions/lua_functions_loader.cpp +++ b/src/lua/functions/lua_functions_loader.cpp @@ -7,6 +7,8 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/lua_functions_loader.hpp" + #include "creatures/combat/spells.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/npcs/npc.hpp" @@ -20,7 +22,6 @@ #include "lua/functions/creatures/creature_functions.hpp" #include "lua/functions/events/events_functions.hpp" #include "lua/functions/items/item_functions.hpp" -#include "lua/functions/lua_functions_loader.hpp" #include "lua/functions/map/map_functions.hpp" #include "lua/functions/core/game/zone_functions.hpp" #include "lua/global/lua_variant.hpp" @@ -29,7 +30,7 @@ class LuaScriptInterface; -void LuaFunctionsLoader::load(lua_State* L) { +void Lua::load(lua_State* L) { if (!L) { g_game().dieSafely("Invalid lua state, cannot load lua functions."); } @@ -44,7 +45,7 @@ void LuaFunctionsLoader::load(lua_State* L) { ZoneFunctions::init(L); } -std::string LuaFunctionsLoader::getErrorDesc(ErrorCode_t code) { +std::string Lua::getErrorDesc(ErrorCode_t code) { switch (code) { case LUA_ERROR_PLAYER_NOT_FOUND: return "Player not found"; @@ -91,21 +92,21 @@ std::string LuaFunctionsLoader::getErrorDesc(ErrorCode_t code) { } } -int LuaFunctionsLoader::protectedCall(lua_State* L, int nargs, int nresults) { +int Lua::protectedCall(lua_State* L, int nargs, int nresults) { if (const int ret = validateDispatcherContext(__FUNCTION__); ret != 0) { return ret; } - int error_index = lua_gettop(L) - nargs; + const int error_index = lua_gettop(L) - nargs; lua_pushcfunction(L, luaErrorHandler); lua_insert(L, error_index); - int ret = lua_pcall(L, nargs, nresults, error_index); + const int ret = lua_pcall(L, nargs, nresults, error_index); lua_remove(L, error_index); return ret; } -void LuaFunctionsLoader::reportError(const char* function, const std::string &error_desc, bool stack_trace /* = false*/) { +void Lua::reportError(const char* function, const std::string &error_desc, bool stack_trace /* = false*/) { int32_t scriptId; int32_t callbackId; bool timerEvent; @@ -132,7 +133,7 @@ void LuaFunctionsLoader::reportError(const char* function, const std::string &er } logMsg << "Error Description: " << error_desc << "\n"; if (stack_trace && scriptInterface) { - std::string stackTrace = scriptInterface->getStackTrace(error_desc); + const std::string stackTrace = scriptInterface->getStackTrace(error_desc); if (!stackTrace.empty() && stackTrace != "N/A") { logMsg << "Stack Trace:\n" << stackTrace << "\n"; @@ -143,9 +144,9 @@ void LuaFunctionsLoader::reportError(const char* function, const std::string &er g_logger().error(logMsg.str()); } -int LuaFunctionsLoader::luaErrorHandler(lua_State* L) { +int Lua::luaErrorHandler(lua_State* L) { const std::string &errorMessage = popString(L); - auto interface = getScriptEnv()->getScriptInterface(); + const auto interface = getScriptEnv()->getScriptInterface(); if (!interface) { g_logger().error("[{}]: LuaScriptInterface not found, error: {}", __FUNCTION__, errorMessage); return 0; @@ -156,7 +157,7 @@ int LuaFunctionsLoader::luaErrorHandler(lua_State* L) { return 1; } -void LuaFunctionsLoader::pushVariant(lua_State* L, const LuaVariant &var) { +void Lua::pushVariant(lua_State* L, const LuaVariant &var) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -184,7 +185,7 @@ void LuaFunctionsLoader::pushVariant(lua_State* L, const LuaVariant &var) { setMetatable(L, -1, "Variant"); } -void LuaFunctionsLoader::pushThing(lua_State* L, std::shared_ptr<Thing> thing) { +void Lua::pushThing(lua_State* L, const std::shared_ptr<Thing> &thing) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -198,10 +199,10 @@ void LuaFunctionsLoader::pushThing(lua_State* L, std::shared_ptr<Thing> thing) { return; } - if (std::shared_ptr<Item> item = thing->getItem()) { + if (const auto &item = thing->getItem()) { pushUserdata<Item>(L, item); setItemMetatable(L, -1, item); - } else if (std::shared_ptr<Creature> creature = thing->getCreature()) { + } else if (const auto &creature = thing->getCreature()) { pushUserdata<Creature>(L, creature); setCreatureMetatable(L, -1, creature); } else { @@ -209,18 +210,18 @@ void LuaFunctionsLoader::pushThing(lua_State* L, std::shared_ptr<Thing> thing) { } } -void LuaFunctionsLoader::pushCylinder(lua_State* L, std::shared_ptr<Cylinder> cylinder) { +void Lua::pushCylinder(lua_State* L, const std::shared_ptr<Cylinder> &cylinder) { if (validateDispatcherContext(__FUNCTION__)) { return; } - if (std::shared_ptr<Creature> creature = cylinder->getCreature()) { + if (const auto &creature = cylinder->getCreature()) { pushUserdata<Creature>(L, creature); setCreatureMetatable(L, -1, creature); - } else if (std::shared_ptr<Item> parentItem = cylinder->getItem()) { + } else if (const auto &parentItem = cylinder->getItem()) { pushUserdata<Item>(L, parentItem); setItemMetatable(L, -1, parentItem); - } else if (std::shared_ptr<Tile> tile = cylinder->getTile()) { + } else if (const auto &tile = cylinder->getTile()) { pushUserdata<Tile>(L, tile); setMetatable(L, -1, "Tile"); } else if (cylinder == VirtualCylinder::virtualCylinder) { @@ -230,7 +231,7 @@ void LuaFunctionsLoader::pushCylinder(lua_State* L, std::shared_ptr<Cylinder> cy } } -void LuaFunctionsLoader::pushString(lua_State* L, const std::string &value) { +void Lua::pushString(lua_State* L, const std::string &value) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -238,7 +239,15 @@ void LuaFunctionsLoader::pushString(lua_State* L, const std::string &value) { lua_pushlstring(L, value.c_str(), value.length()); } -void LuaFunctionsLoader::pushCallback(lua_State* L, int32_t callback) { +void Lua::pushNumber(lua_State* L, lua_Number value) { + if (validateDispatcherContext(__FUNCTION__)) { + return; + } + + lua_pushnumber(L, value); +} + +void Lua::pushCallback(lua_State* L, int32_t callback) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -246,9 +255,9 @@ void LuaFunctionsLoader::pushCallback(lua_State* L, int32_t callback) { lua_rawgeti(L, LUA_REGISTRYINDEX, callback); } -std::string LuaFunctionsLoader::popString(lua_State* L) { +std::string Lua::popString(lua_State* L) { if (lua_gettop(L) == 0) { - return std::string(); + return {}; } std::string str(getString(L, -1)); @@ -256,12 +265,12 @@ std::string LuaFunctionsLoader::popString(lua_State* L) { return str; } -int32_t LuaFunctionsLoader::popCallback(lua_State* L) { +int32_t Lua::popCallback(lua_State* L) { return luaL_ref(L, LUA_REGISTRYINDEX); } // Metatables -void LuaFunctionsLoader::setMetatable(lua_State* L, int32_t index, const std::string &name) { +void Lua::setMetatable(lua_State* L, int32_t index, const std::string &name) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -270,7 +279,7 @@ void LuaFunctionsLoader::setMetatable(lua_State* L, int32_t index, const std::st lua_setmetatable(L, index - 1); } -void LuaFunctionsLoader::setWeakMetatable(lua_State* L, int32_t index, const std::string &name) { +void Lua::setWeakMetatable(lua_State* L, int32_t index, const std::string &name) { static phmap::flat_hash_set<std::string> weakObjectTypes; if (validateDispatcherContext(__FUNCTION__)) { return; @@ -278,13 +287,13 @@ void LuaFunctionsLoader::setWeakMetatable(lua_State* L, int32_t index, const std const std::string &weakName = name + "_weak"; - auto result = weakObjectTypes.emplace(name); + const auto result = weakObjectTypes.emplace(name); if (result.second) { luaL_getmetatable(L, name.c_str()); - int childMetatable = lua_gettop(L); + const int childMetatable = lua_gettop(L); luaL_newmetatable(L, weakName.c_str()); - int metatable = lua_gettop(L); + const int metatable = lua_gettop(L); for (static const std::vector<std::string> methodKeys = { "__index", "__metatable", "__eq" }; const std::string &metaKey : methodKeys) { @@ -293,7 +302,7 @@ void LuaFunctionsLoader::setWeakMetatable(lua_State* L, int32_t index, const std } for (static const std::vector<int> methodIndexes = { 'h', 'p', 't' }; - int metaIndex : methodIndexes) { + const int metaIndex : methodIndexes) { lua_rawgeti(L, childMetatable, metaIndex); lua_rawseti(L, metatable, metaIndex); } @@ -308,7 +317,7 @@ void LuaFunctionsLoader::setWeakMetatable(lua_State* L, int32_t index, const std lua_setmetatable(L, index - 1); } -void LuaFunctionsLoader::setItemMetatable(lua_State* L, int32_t index, std::shared_ptr<Item> item) { +void Lua::setItemMetatable(lua_State* L, int32_t index, const std::shared_ptr<Item> &item) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -323,7 +332,7 @@ void LuaFunctionsLoader::setItemMetatable(lua_State* L, int32_t index, std::shar lua_setmetatable(L, index - 1); } -void LuaFunctionsLoader::setCreatureMetatable(lua_State* L, int32_t index, std::shared_ptr<Creature> creature) { +void Lua::setCreatureMetatable(lua_State* L, int32_t index, const std::shared_ptr<Creature> &creature) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -338,7 +347,7 @@ void LuaFunctionsLoader::setCreatureMetatable(lua_State* L, int32_t index, std:: lua_setmetatable(L, index - 1); } -CombatDamage LuaFunctionsLoader::getCombatDamage(lua_State* L) { +CombatDamage Lua::getCombatDamage(lua_State* L) { CombatDamage damage; damage.primary.value = getNumber<int32_t>(L, -4); damage.primary.type = getNumber<CombatType_t>(L, -3); @@ -350,9 +359,9 @@ CombatDamage LuaFunctionsLoader::getCombatDamage(lua_State* L) { } // Get -std::string LuaFunctionsLoader::getFormatedLoggerMessage(lua_State* L) { - std::string format = getString(L, 1); - int n = lua_gettop(L); +std::string Lua::getFormatedLoggerMessage(lua_State* L) { + const std::string format = getString(L, 1); + const int n = lua_gettop(L); fmt::dynamic_format_arg_store<fmt::format_context> args; for (int i = 2; i <= n; i++) { @@ -363,7 +372,7 @@ std::string LuaFunctionsLoader::getFormatedLoggerMessage(lua_State* L) { } else if (isBoolean(L, i)) { args.push_back(lua_toboolean(L, i) ? "true" : "false"); } else if (isUserdata(L, i)) { - LuaData_t userType = getUserdataType(L, i); + const LuaData_t userType = getUserdataType(L, i); args.push_back(getUserdataTypeName(userType)); } else if (isTable(L, i)) { args.push_back("table"); @@ -386,16 +395,16 @@ std::string LuaFunctionsLoader::getFormatedLoggerMessage(lua_State* L) { return {}; } -std::string LuaFunctionsLoader::getString(lua_State* L, int32_t arg) { +std::string Lua::getString(lua_State* L, int32_t arg) { size_t len; const char* c_str = lua_tolstring(L, arg, &len); if (!c_str || len == 0) { - return std::string(); + return {}; } return std::string(c_str, len); } -Position LuaFunctionsLoader::getPosition(lua_State* L, int32_t arg, int32_t &stackpos) { +Position Lua::getPosition(lua_State* L, int32_t arg, int32_t &stackpos) { Position position; position.x = getField<uint16_t>(L, arg, "x"); position.y = getField<uint16_t>(L, arg, "y"); @@ -412,7 +421,7 @@ Position LuaFunctionsLoader::getPosition(lua_State* L, int32_t arg, int32_t &sta return position; } -Position LuaFunctionsLoader::getPosition(lua_State* L, int32_t arg) { +Position Lua::getPosition(lua_State* L, int32_t arg) { Position position; position.x = getField<uint16_t>(L, arg, "x"); position.y = getField<uint16_t>(L, arg, "y"); @@ -422,7 +431,7 @@ Position LuaFunctionsLoader::getPosition(lua_State* L, int32_t arg) { return position; } -Outfit_t LuaFunctionsLoader::getOutfit(lua_State* L, int32_t arg) { +Outfit_t Lua::getOutfit(lua_State* L, int32_t arg) { Outfit_t outfit; outfit.lookMountFeet = getField<uint8_t>(L, arg, "lookMountFeet"); outfit.lookMountLegs = getField<uint8_t>(L, arg, "lookMountLegs"); @@ -444,7 +453,7 @@ Outfit_t LuaFunctionsLoader::getOutfit(lua_State* L, int32_t arg) { return outfit; } -LuaVariant LuaFunctionsLoader::getVariant(lua_State* L, int32_t arg) { +LuaVariant Lua::getVariant(lua_State* L, int32_t arg) { LuaVariant var; var.instantName = getFieldString(L, arg, "instantName"); var.runeName = getFieldString(L, arg, "runeName"); @@ -478,7 +487,7 @@ LuaVariant LuaFunctionsLoader::getVariant(lua_State* L, int32_t arg) { return var; } -std::shared_ptr<Thing> LuaFunctionsLoader::getThing(lua_State* L, int32_t arg) { +std::shared_ptr<Thing> Lua::getThing(lua_State* L, int32_t arg) { std::shared_ptr<Thing> thing; if (lua_getmetatable(L, arg) != 0) { lua_rawgeti(L, -1, 't'); @@ -512,14 +521,14 @@ std::shared_ptr<Thing> LuaFunctionsLoader::getThing(lua_State* L, int32_t arg) { return thing; } -std::shared_ptr<Creature> LuaFunctionsLoader::getCreature(lua_State* L, int32_t arg) { +std::shared_ptr<Creature> Lua::getCreature(lua_State* L, int32_t arg) { if (isUserdata(L, arg)) { return getUserdataShared<Creature>(L, arg); } return g_game().getCreatureByID(getNumber<uint32_t>(L, arg)); } -std::shared_ptr<Player> LuaFunctionsLoader::getPlayer(lua_State* L, int32_t arg, bool allowOffline /* = false */) { +std::shared_ptr<Player> Lua::getPlayer(lua_State* L, int32_t arg, bool allowOffline /* = false */) { if (isUserdata(L, arg)) { return getUserdataShared<Player>(L, arg); } else if (isNumber(L, arg)) { @@ -527,11 +536,11 @@ std::shared_ptr<Player> LuaFunctionsLoader::getPlayer(lua_State* L, int32_t arg, } else if (isString(L, arg)) { return g_game().getPlayerByName(getString(L, arg), allowOffline); } - g_logger().warn("LuaFunctionsLoader::getPlayer: Invalid argument."); + g_logger().warn("Lua::getPlayer: Invalid argument."); return nullptr; } -std::shared_ptr<Guild> LuaFunctionsLoader::getGuild(lua_State* L, int32_t arg, bool allowOffline /* = false */) { +std::shared_ptr<Guild> Lua::getGuild(lua_State* L, int32_t arg, bool allowOffline /* = false */) { if (isUserdata(L, arg)) { return getUserdataShared<Guild>(L, arg); } else if (isNumber(L, arg)) { @@ -539,33 +548,33 @@ std::shared_ptr<Guild> LuaFunctionsLoader::getGuild(lua_State* L, int32_t arg, b } else if (isString(L, arg)) { return g_game().getGuildByName(getString(L, arg), allowOffline); } - g_logger().warn("LuaFunctionsLoader::getGuild: Invalid argument."); + g_logger().warn("Lua::getGuild: Invalid argument."); return nullptr; } -std::string LuaFunctionsLoader::getFieldString(lua_State* L, int32_t arg, const std::string &key) { +std::string Lua::getFieldString(lua_State* L, int32_t arg, const std::string &key) { lua_getfield(L, arg, key.c_str()); return getString(L, -1); } -LuaData_t LuaFunctionsLoader::getUserdataType(lua_State* L, int32_t arg) { +LuaData_t Lua::getUserdataType(lua_State* L, int32_t arg) { if (lua_getmetatable(L, arg) == 0) { return LuaData_t::Unknown; } lua_rawgeti(L, -1, 't'); - LuaData_t type = getNumber<LuaData_t>(L, -1); + const LuaData_t type = getNumber<LuaData_t>(L, -1); lua_pop(L, 2); return type; } -std::string LuaFunctionsLoader::getUserdataTypeName(LuaData_t userType) { +std::string Lua::getUserdataTypeName(LuaData_t userType) { return magic_enum::enum_name(userType).data(); } // Push -void LuaFunctionsLoader::pushBoolean(lua_State* L, bool value) { +void Lua::pushBoolean(lua_State* L, bool value) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -573,7 +582,7 @@ void LuaFunctionsLoader::pushBoolean(lua_State* L, bool value) { lua_pushboolean(L, value ? 1 : 0); } -void LuaFunctionsLoader::pushCombatDamage(lua_State* L, const CombatDamage &damage) { +void Lua::pushCombatDamage(lua_State* L, const CombatDamage &damage) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -585,7 +594,7 @@ void LuaFunctionsLoader::pushCombatDamage(lua_State* L, const CombatDamage &dama lua_pushnumber(L, damage.origin); } -void LuaFunctionsLoader::pushInstantSpell(lua_State* L, const InstantSpell &spell) { +void Lua::pushInstantSpell(lua_State* L, const InstantSpell &spell) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -602,7 +611,7 @@ void LuaFunctionsLoader::pushInstantSpell(lua_State* L, const InstantSpell &spel setMetatable(L, -1, "Spell"); } -void LuaFunctionsLoader::pushPosition(lua_State* L, const Position &position, int32_t stackpos /* = 0*/) { +void Lua::pushPosition(lua_State* L, const Position &position, int32_t stackpos /* = 0*/) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -617,7 +626,7 @@ void LuaFunctionsLoader::pushPosition(lua_State* L, const Position &position, in setMetatable(L, -1, "Position"); } -void LuaFunctionsLoader::pushOutfit(lua_State* L, const Outfit_t &outfit) { +void Lua::pushOutfit(lua_State* L, const Outfit_t &outfit) { if (validateDispatcherContext(__FUNCTION__)) { return; } @@ -638,16 +647,16 @@ void LuaFunctionsLoader::pushOutfit(lua_State* L, const Outfit_t &outfit) { setField(L, "lookFamiliarsType", outfit.lookFamiliarsType); } -void LuaFunctionsLoader::registerClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction /* = nullptr*/) { +void Lua::registerClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction /* = nullptr*/) { // className = {} lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, className.c_str()); - int methods = lua_gettop(L); + const int methods = lua_gettop(L); // methodsTable = {} lua_newtable(L); - int methodsTable = lua_gettop(L); + const int methodsTable = lua_gettop(L); if (newFunction) { // className.__call = newFunction @@ -669,7 +678,7 @@ void LuaFunctionsLoader::registerClass(lua_State* L, const std::string &classNam // className.metatable = {} luaL_newmetatable(L, className.c_str()); - int metatable = lua_gettop(L); + const int metatable = lua_gettop(L); // className.metatable.__metatable = className lua_pushvalue(L, methods); @@ -700,7 +709,7 @@ void LuaFunctionsLoader::registerClass(lua_State* L, const std::string &classNam lua_pop(L, 2); } -void LuaFunctionsLoader::registerMethod(lua_State* L, const std::string &globalName, const std::string &methodName, lua_CFunction func) { +void Lua::registerMethod(lua_State* L, const std::string &globalName, const std::string &methodName, lua_CFunction func) { // globalName.methodName = func lua_getglobal(L, globalName.c_str()); lua_pushcfunction(L, func); @@ -710,13 +719,13 @@ void LuaFunctionsLoader::registerMethod(lua_State* L, const std::string &globalN lua_pop(L, 1); } -void LuaFunctionsLoader::registerTable(lua_State* L, const std::string &tableName) { +void Lua::registerTable(lua_State* L, const std::string &tableName) { // _G[tableName] = {} lua_newtable(L); lua_setglobal(L, tableName.c_str()); } -void LuaFunctionsLoader::registerMetaMethod(lua_State* L, const std::string &className, const std::string &methodName, lua_CFunction func) { +void Lua::registerMetaMethod(lua_State* L, const std::string &className, const std::string &methodName, lua_CFunction func) { // className.metatable.methodName = func luaL_getmetatable(L, className.c_str()); lua_pushcfunction(L, func); @@ -726,7 +735,7 @@ void LuaFunctionsLoader::registerMetaMethod(lua_State* L, const std::string &cla lua_pop(L, 1); } -void LuaFunctionsLoader::registerVariable(lua_State* L, const std::string &tableName, const std::string &name, lua_Number value) { +void Lua::registerVariable(lua_State* L, const std::string &tableName, const std::string &name, lua_Number value) { // tableName.name = value lua_getglobal(L, tableName.c_str()); setField(L, name.c_str(), value); @@ -735,31 +744,31 @@ void LuaFunctionsLoader::registerVariable(lua_State* L, const std::string &table lua_pop(L, 1); } -void LuaFunctionsLoader::registerGlobalBoolean(lua_State* L, const std::string &name, bool value) { +void Lua::registerGlobalBoolean(lua_State* L, const std::string &name, bool value) { // _G[name] = value pushBoolean(L, value); lua_setglobal(L, name.c_str()); } -void LuaFunctionsLoader::registerGlobalMethod(lua_State* L, const std::string &functionName, lua_CFunction func) { +void Lua::registerGlobalMethod(lua_State* L, const std::string &functionName, lua_CFunction func) { // _G[functionName] = func lua_pushcfunction(L, func); lua_setglobal(L, functionName.c_str()); } -void LuaFunctionsLoader::registerGlobalVariable(lua_State* L, const std::string &name, lua_Number value) { +void Lua::registerGlobalVariable(lua_State* L, const std::string &name, lua_Number value) { // _G[name] = value lua_pushnumber(L, value); lua_setglobal(L, name.c_str()); } -void LuaFunctionsLoader::registerGlobalString(lua_State* L, const std::string &variable, const std::string &name) { +void Lua::registerGlobalString(lua_State* L, const std::string &variable, const std::string &name) { // Example: registerGlobalString(L, "VARIABLE_NAME", "variable string"); pushString(L, name); lua_setglobal(L, variable.c_str()); } -std::string LuaFunctionsLoader::escapeString(const std::string &string) { +std::string Lua::escapeString(const std::string &string) { std::string s = string; replaceString(s, "\\", "\\\\"); replaceString(s, "\"", "\\\""); @@ -768,26 +777,26 @@ std::string LuaFunctionsLoader::escapeString(const std::string &string) { return s; } -int LuaFunctionsLoader::luaUserdataCompare(lua_State* L) { +int Lua::luaUserdataCompare(lua_State* L) { pushBoolean(L, getUserdata<void>(L, 1) == getUserdata<void>(L, 2)); return 1; } -void LuaFunctionsLoader::registerSharedClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction) { +void Lua::registerSharedClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction) { registerClass(L, className, baseClass, newFunction); registerMetaMethod(L, className, "__gc", luaGarbageCollection); } -int LuaFunctionsLoader::luaGarbageCollection(lua_State* L) { - auto objPtr = static_cast<std::shared_ptr<SharedObject>*>(lua_touserdata(L, 1)); +int Lua::luaGarbageCollection(lua_State* L) { + const auto objPtr = static_cast<std::shared_ptr<SharedObject>*>(lua_touserdata(L, 1)); if (objPtr) { objPtr->reset(); } return 0; } -int LuaFunctionsLoader::validateDispatcherContext(std::string_view fncName) { - if (g_dispatcher().context().isOn() && g_dispatcher().context().isAsync()) { +int Lua::validateDispatcherContext(std::string_view fncName) { + if (DispatcherContext::isOn() && g_dispatcher().context().isAsync()) { g_logger().warn("[{}] The call to lua was ignored because the '{}' task is trying to communicate while in async mode.", fncName, g_dispatcher().context().getName()); return LUA_ERRRUN; } diff --git a/src/lua/functions/lua_functions_loader.hpp b/src/lua/functions/lua_functions_loader.hpp index e5251e3a1c3..68cfeb45c51 100644 --- a/src/lua/functions/lua_functions_loader.hpp +++ b/src/lua/functions/lua_functions_loader.hpp @@ -26,11 +26,13 @@ class Guild; class Zone; class KV; +using lua_Number = double; + struct LuaVariant; #define reportErrorFunc(a) reportError(__FUNCTION__, a, true) -class LuaFunctionsLoader { +class Lua { public: static void load(lua_State* L); @@ -39,11 +41,12 @@ class LuaFunctionsLoader { static void reportError(const char* function, const std::string &error_desc, bool stack_trace = false); static int luaErrorHandler(lua_State* L); - static void pushThing(lua_State* L, std::shared_ptr<Thing> thing); + static void pushThing(lua_State* L, const std::shared_ptr<Thing> &thing); static void pushVariant(lua_State* L, const LuaVariant &var); static void pushString(lua_State* L, const std::string &value); + static void pushNumber(lua_State* L, lua_Number value); static void pushCallback(lua_State* L, int32_t callback); - static void pushCylinder(lua_State* L, std::shared_ptr<Cylinder> cylinder); + static void pushCylinder(lua_State* L, const std::shared_ptr<Cylinder> &cylinder); static std::string popString(lua_State* L); static int32_t popCallback(lua_State* L); @@ -56,27 +59,33 @@ class LuaFunctionsLoader { static void setMetatable(lua_State* L, int32_t index, const std::string &name); static void setWeakMetatable(lua_State* L, int32_t index, const std::string &name); - static void setItemMetatable(lua_State* L, int32_t index, std::shared_ptr<Item> item); - static void setCreatureMetatable(lua_State* L, int32_t index, std::shared_ptr<Creature> creature); + static void setItemMetatable(lua_State* L, int32_t index, const std::shared_ptr<Item> &item); + static void setCreatureMetatable(lua_State* L, int32_t index, const std::shared_ptr<Creature> &creature); template <typename T> - static typename std::enable_if<std::is_enum<T>::value, T>::type - getNumber(lua_State* L, int32_t arg) { - return static_cast<T>(static_cast<int64_t>(lua_tonumber(L, arg))); - } - template <typename T> - static typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value, T>::type getNumber(lua_State* L, int32_t arg) { + static T getNumber(lua_State* L, int32_t arg, std::source_location location = std::source_location::current()) { auto number = lua_tonumber(L, arg); - // If there is overflow, we return the value 0 - if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) { - if (number < 0) { - g_logger().debug("[{}] overflow, setting to default signed value (0)", __FUNCTION__); - number = T(0); + + if constexpr (std::is_enum_v<T>) { + return static_cast<T>(static_cast<int64_t>(number)); + } + + if constexpr (std::is_integral_v<T>) { + if constexpr (std::is_unsigned_v<T>) { + if (number < 0) { + g_logger().debug("[{}] overflow, setting to default unsigned value (0), called line: {}:{}, in {}", __FUNCTION__, location.line(), location.column(), location.function_name()); + return T(0); + } } + return static_cast<T>(number); + } + if constexpr (std::is_floating_point_v<T>) { + return static_cast<T>(number); } - return static_cast<T>(number); + return T {}; } + template <typename T> static T getNumber(lua_State* L, int32_t arg, T defaultValue) { const auto parameters = lua_gettop(L); @@ -228,7 +237,6 @@ class LuaFunctionsLoader { new (userData) std::shared_ptr<T>(value); } -protected: static void registerClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction = nullptr); static void registerSharedClass(lua_State* L, const std::string &className, const std::string &baseClass, lua_CFunction newFunction = nullptr); static void registerMethod(lua_State* L, const std::string &globalName, const std::string &methodName, lua_CFunction func); diff --git a/src/lua/functions/map/house_functions.cpp b/src/lua/functions/map/house_functions.cpp index 597eec3975e..10ebbc2cf0c 100644 --- a/src/lua/functions/map/house_functions.cpp +++ b/src/lua/functions/map/house_functions.cpp @@ -7,18 +7,59 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/map/house_functions.hpp" + +#include "config/configmanager.hpp" #include "items/bed.hpp" #include "game/game.hpp" #include "game/movement/position.hpp" #include "io/iologindata.hpp" -#include "lua/functions/map/house_functions.hpp" #include "map/house/house.hpp" +#include "creatures/players/player.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void HouseFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "House", "", HouseFunctions::luaHouseCreate); + Lua::registerMetaMethod(L, "House", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "House", "getId", HouseFunctions::luaHouseGetId); + Lua::registerMethod(L, "House", "getName", HouseFunctions::luaHouseGetName); + Lua::registerMethod(L, "House", "getTown", HouseFunctions::luaHouseGetTown); + Lua::registerMethod(L, "House", "getExitPosition", HouseFunctions::luaHouseGetExitPosition); + Lua::registerMethod(L, "House", "getRent", HouseFunctions::luaHouseGetRent); + Lua::registerMethod(L, "House", "getPrice", HouseFunctions::luaHouseGetPrice); + + Lua::registerMethod(L, "House", "getOwnerGuid", HouseFunctions::luaHouseGetOwnerGuid); + Lua::registerMethod(L, "House", "setHouseOwner", HouseFunctions::luaHouseSetHouseOwner); + Lua::registerMethod(L, "House", "setNewOwnerGuid", HouseFunctions::luaHouseSetNewOwnerGuid); + Lua::registerMethod(L, "House", "hasItemOnTile", HouseFunctions::luaHouseHasItemOnTile); + Lua::registerMethod(L, "House", "hasNewOwnership", HouseFunctions::luaHouseHasNewOwnership); + Lua::registerMethod(L, "House", "startTrade", HouseFunctions::luaHouseStartTrade); + + Lua::registerMethod(L, "House", "getBeds", HouseFunctions::luaHouseGetBeds); + Lua::registerMethod(L, "House", "getBedCount", HouseFunctions::luaHouseGetBedCount); + + Lua::registerMethod(L, "House", "getDoors", HouseFunctions::luaHouseGetDoors); + Lua::registerMethod(L, "House", "getDoorCount", HouseFunctions::luaHouseGetDoorCount); + Lua::registerMethod(L, "House", "getDoorIdByPosition", HouseFunctions::luaHouseGetDoorIdByPosition); + + Lua::registerMethod(L, "House", "getTiles", HouseFunctions::luaHouseGetTiles); + Lua::registerMethod(L, "House", "getItems", HouseFunctions::luaHouseGetItems); + Lua::registerMethod(L, "House", "getTileCount", HouseFunctions::luaHouseGetTileCount); + + Lua::registerMethod(L, "House", "canEditAccessList", HouseFunctions::luaHouseCanEditAccessList); + Lua::registerMethod(L, "House", "getAccessList", HouseFunctions::luaHouseGetAccessList); + Lua::registerMethod(L, "House", "setAccessList", HouseFunctions::luaHouseSetAccessList); + + Lua::registerMethod(L, "House", "kickPlayer", HouseFunctions::luaHouseKickPlayer); + Lua::registerMethod(L, "House", "isInvited", HouseFunctions::luaHouseIsInvited); +} int HouseFunctions::luaHouseCreate(lua_State* L) { // House(id) - if (const auto &house = g_game().map.houses.getHouse(getNumber<uint32_t>(L, 2))) { - pushUserdata<House>(L, house); - setMetatable(L, -1, "House"); + if (const auto &house = g_game().map.houses.getHouse(Lua::getNumber<uint32_t>(L, 2))) { + Lua::pushUserdata<House>(L, house); + Lua::setMetatable(L, -1, "House"); } else { lua_pushnil(L); } @@ -27,7 +68,7 @@ int HouseFunctions::luaHouseCreate(lua_State* L) { int HouseFunctions::luaHouseGetId(lua_State* L) { // house:getId() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getId()); } else { lua_pushnil(L); @@ -37,8 +78,8 @@ int HouseFunctions::luaHouseGetId(lua_State* L) { int HouseFunctions::luaHouseGetName(lua_State* L) { // house:getName() - if (const auto &house = getUserdataShared<House>(L, 1)) { - pushString(L, house->getName()); + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { + Lua::pushString(L, house->getName()); } else { lua_pushnil(L); } @@ -47,15 +88,15 @@ int HouseFunctions::luaHouseGetName(lua_State* L) { int HouseFunctions::luaHouseGetTown(lua_State* L) { // house:getTown() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } if (const auto &town = g_game().map.towns.getTown(house->getTownId())) { - pushUserdata<Town>(L, town); - setMetatable(L, -1, "Town"); + Lua::pushUserdata<Town>(L, town); + Lua::setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } @@ -64,8 +105,8 @@ int HouseFunctions::luaHouseGetTown(lua_State* L) { int HouseFunctions::luaHouseGetExitPosition(lua_State* L) { // house:getExitPosition() - if (const auto &house = getUserdataShared<House>(L, 1)) { - pushPosition(L, house->getEntryPosition()); + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { + Lua::pushPosition(L, house->getEntryPosition()); } else { lua_pushnil(L); } @@ -74,7 +115,7 @@ int HouseFunctions::luaHouseGetExitPosition(lua_State* L) { int HouseFunctions::luaHouseGetRent(lua_State* L) { // house:getRent() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getRent()); } else { lua_pushnil(L); @@ -84,9 +125,9 @@ int HouseFunctions::luaHouseGetRent(lua_State* L) { int HouseFunctions::luaHouseGetPrice(lua_State* L) { // house:getPrice() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { - reportErrorFunc("House not found"); + Lua::reportErrorFunc("House not found"); lua_pushnumber(L, 0); return 1; } @@ -97,7 +138,7 @@ int HouseFunctions::luaHouseGetPrice(lua_State* L) { int HouseFunctions::luaHouseGetOwnerGuid(lua_State* L) { // house:getOwnerGuid() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getOwner()); } else { lua_pushnil(L); @@ -107,27 +148,27 @@ int HouseFunctions::luaHouseGetOwnerGuid(lua_State* L) { int HouseFunctions::luaHouseSetHouseOwner(lua_State* L) { // house:setHouseOwner(guid[, updateDatabase = true]) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { - reportErrorFunc("House not found"); + Lua::reportErrorFunc("House not found"); lua_pushnil(L); return 1; } - uint32_t guid = getNumber<uint32_t>(L, 2); - bool updateDatabase = getBoolean(L, 3, true); + const uint32_t guid = Lua::getNumber<uint32_t>(L, 2); + const bool updateDatabase = Lua::getBoolean(L, 3, true); house->setOwner(guid, updateDatabase); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int HouseFunctions::luaHouseSetNewOwnerGuid(lua_State* L) { // house:setNewOwnerGuid(guid[, updateDatabase = true]) - auto house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (house) { auto isTransferOnRestart = g_configManager().getBoolean(TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART); if (isTransferOnRestart && house->hasNewOwnership()) { - const auto player = g_game().getPlayerByGUID(house->getOwner()); + const auto &player = g_game().getPlayerByGUID(house->getOwner()); if (player) { player->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot leave this house. Ownership is already scheduled to be transferred upon the next server restart."); } @@ -135,9 +176,9 @@ int HouseFunctions::luaHouseSetNewOwnerGuid(lua_State* L) { return 1; } - uint32_t guid = getNumber<uint32_t>(L, 2, 0); + const auto guid = Lua::getNumber<uint32_t>(L, 2, 0); house->setNewOwnerGuid(guid, false); - pushBoolean(L, true); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } @@ -146,36 +187,36 @@ int HouseFunctions::luaHouseSetNewOwnerGuid(lua_State* L) { int HouseFunctions::luaHouseHasItemOnTile(lua_State* L) { // house:hasItemOnTile() - auto house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { - reportErrorFunc("House not found"); + Lua::reportErrorFunc("House not found"); lua_pushnil(L); return 1; } - pushBoolean(L, house->hasItemOnTile()); + Lua::pushBoolean(L, house->hasItemOnTile()); return 1; } int HouseFunctions::luaHouseHasNewOwnership(lua_State* L) { // house:hasNewOwnership(guid) - auto house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { - reportErrorFunc("House not found"); + Lua::reportErrorFunc("House not found"); lua_pushnil(L); return 1; } auto isTransferOnRestart = g_configManager().getBoolean(TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART); - pushBoolean(L, isTransferOnRestart && house->hasNewOwnership()); + Lua::pushBoolean(L, isTransferOnRestart && house->hasNewOwnership()); return 1; } int HouseFunctions::luaHouseStartTrade(lua_State* L) { // house:startTrade(player, tradePartner) - const auto &house = getUserdataShared<House>(L, 1); - std::shared_ptr<Player> player = getUserdataShared<Player>(L, 2); - std::shared_ptr<Player> tradePartner = getUserdataShared<Player>(L, 3); + const auto &house = Lua::getUserdataShared<House>(L, 1); + const auto &player = Lua::getUserdataShared<Player>(L, 2); + const auto &tradePartner = Lua::getUserdataShared<Player>(L, 3); if (!player || !tradePartner || !house) { lua_pushnil(L); @@ -202,7 +243,7 @@ int HouseFunctions::luaHouseStartTrade(lua_State* L) { return 1; } - std::shared_ptr<Item> transferItem = house->getTransferItem(); + const auto &transferItem = house->getTransferItem(); if (!transferItem) { lua_pushnumber(L, RETURNVALUE_YOUCANNOTTRADETHISHOUSE); return 1; @@ -227,19 +268,19 @@ int HouseFunctions::luaHouseStartTrade(lua_State* L) { int HouseFunctions::luaHouseGetBeds(lua_State* L) { // house:getBeds() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto beds = house->getBeds(); + const auto &beds = house->getBeds(); lua_createtable(L, beds.size(), 0); int index = 0; - for (std::shared_ptr<BedItem> bedItem : beds) { - pushUserdata<Item>(L, bedItem); - setItemMetatable(L, -1, bedItem); + for (const auto &bedItem : beds) { + Lua::pushUserdata<Item>(L, bedItem); + Lua::setItemMetatable(L, -1, bedItem); lua_rawseti(L, -2, ++index); } return 1; @@ -247,7 +288,7 @@ int HouseFunctions::luaHouseGetBeds(lua_State* L) { int HouseFunctions::luaHouseGetBedCount(lua_State* L) { // house:getBedCount() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getBedCount()); } else { lua_pushnil(L); @@ -257,19 +298,19 @@ int HouseFunctions::luaHouseGetBedCount(lua_State* L) { int HouseFunctions::luaHouseGetDoors(lua_State* L) { // house:getDoors() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto doors = house->getDoors(); + const auto &doors = house->getDoors(); lua_createtable(L, doors.size(), 0); int index = 0; - for (std::shared_ptr<Door> door : doors) { - pushUserdata<Item>(L, door); - setItemMetatable(L, -1, door); + for (const auto &door : doors) { + Lua::pushUserdata<Item>(L, door); + Lua::setItemMetatable(L, -1, door); lua_rawseti(L, -2, ++index); } return 1; @@ -277,7 +318,7 @@ int HouseFunctions::luaHouseGetDoors(lua_State* L) { int HouseFunctions::luaHouseGetDoorCount(lua_State* L) { // house:getDoorCount() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getDoors().size()); } else { lua_pushnil(L); @@ -287,13 +328,13 @@ int HouseFunctions::luaHouseGetDoorCount(lua_State* L) { int HouseFunctions::luaHouseGetDoorIdByPosition(lua_State* L) { // house:getDoorIdByPosition(position) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - std::shared_ptr<Door> door = house->getDoorByPosition(getPosition(L, 2)); + const auto &door = house->getDoorByPosition(Lua::getPosition(L, 2)); if (door) { lua_pushnumber(L, door->getDoorId()); } else { @@ -304,19 +345,19 @@ int HouseFunctions::luaHouseGetDoorIdByPosition(lua_State* L) { int HouseFunctions::luaHouseGetTiles(lua_State* L) { // house:getTiles() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto tiles = house->getTiles(); + const auto &tiles = house->getTiles(); lua_newtable(L); int index = 0; - for (std::shared_ptr<Tile> tile : tiles) { - pushUserdata<Tile>(L, tile); - setMetatable(L, -1, "Tile"); + for (const auto &tile : tiles) { + Lua::pushUserdata<Tile>(L, tile); + Lua::setMetatable(L, -1, "Tile"); lua_rawseti(L, -2, ++index); } return 1; @@ -324,22 +365,22 @@ int HouseFunctions::luaHouseGetTiles(lua_State* L) { int HouseFunctions::luaHouseGetItems(lua_State* L) { // house:getItems() - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto tiles = house->getTiles(); + const auto &tiles = house->getTiles(); lua_newtable(L); int index = 0; - for (std::shared_ptr<Tile> tile : tiles) { - TileItemVector* itemVector = tile->getItemList(); + for (const auto &tile : tiles) { + const TileItemVector* itemVector = tile->getItemList(); if (itemVector) { - for (auto &item : *itemVector) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + for (const auto &item : *itemVector) { + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); lua_rawseti(L, -2, ++index); } } @@ -349,7 +390,7 @@ int HouseFunctions::luaHouseGetItems(lua_State* L) { int HouseFunctions::luaHouseGetTileCount(lua_State* L) { // house:getTileCount() - if (const auto &house = getUserdataShared<House>(L, 1)) { + if (const auto &house = Lua::getUserdataShared<House>(L, 1)) { lua_pushnumber(L, house->getTiles().size()); } else { lua_pushnil(L); @@ -359,95 +400,95 @@ int HouseFunctions::luaHouseGetTileCount(lua_State* L) { int HouseFunctions::luaHouseCanEditAccessList(lua_State* L) { // house:canEditAccessList(listId, player) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - uint32_t listId = getNumber<uint32_t>(L, 2); + const uint32_t listId = Lua::getNumber<uint32_t>(L, 2); - const auto &player = getPlayer(L, 3); + const auto &player = Lua::getPlayer(L, 3); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - pushBoolean(L, house->canEditAccessList(listId, player)); + Lua::pushBoolean(L, house->canEditAccessList(listId, player)); return 1; } int HouseFunctions::luaHouseGetAccessList(lua_State* L) { // house:getAccessList(listId) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } std::string list; - uint32_t listId = getNumber<uint32_t>(L, 2); + const uint32_t listId = Lua::getNumber<uint32_t>(L, 2); if (house->getAccessList(listId, list)) { - pushString(L, list); + Lua::pushString(L, list); } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int HouseFunctions::luaHouseSetAccessList(lua_State* L) { // house:setAccessList(listId, list) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - uint32_t listId = getNumber<uint32_t>(L, 2); - const std::string &list = getString(L, 3); + const uint32_t listId = Lua::getNumber<uint32_t>(L, 2); + const std::string &list = Lua::getString(L, 3); house->setAccessList(listId, list); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int HouseFunctions::luaHouseKickPlayer(lua_State* L) { // house:kickPlayer(player, targetPlayer) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc("Player is nullptr"); + Lua::reportErrorFunc("Player is nullptr"); return 1; } - auto targetPlayer = getPlayer(L, 3); + const auto &targetPlayer = Lua::getPlayer(L, 3); if (!targetPlayer) { - reportErrorFunc("Target player is nullptr"); + Lua::reportErrorFunc("Target player is nullptr"); return 1; } - pushBoolean(L, house->kickPlayer(player, targetPlayer)); + Lua::pushBoolean(L, house->kickPlayer(player, targetPlayer)); return 1; } int HouseFunctions::luaHouseIsInvited(lua_State* L) { // house:isInvited(player) - const auto &house = getUserdataShared<House>(L, 1); + const auto &house = Lua::getUserdataShared<House>(L, 1); if (!house) { lua_pushnil(L); return 1; } - const auto &player = getPlayer(L, 2); + const auto &player = Lua::getPlayer(L, 2); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } - pushBoolean(L, house->isInvited(player)); + Lua::pushBoolean(L, house->isInvited(player)); return 1; } diff --git a/src/lua/functions/map/house_functions.hpp b/src/lua/functions/map/house_functions.hpp index ede7e1f0998..bb7200a5b3f 100644 --- a/src/lua/functions/map/house_functions.hpp +++ b/src/lua/functions/map/house_functions.hpp @@ -9,46 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class HouseFunctions final : LuaScriptInterface { +class HouseFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "House", "", HouseFunctions::luaHouseCreate); - registerMetaMethod(L, "House", "__eq", HouseFunctions::luaUserdataCompare); - - registerMethod(L, "House", "getId", HouseFunctions::luaHouseGetId); - registerMethod(L, "House", "getName", HouseFunctions::luaHouseGetName); - registerMethod(L, "House", "getTown", HouseFunctions::luaHouseGetTown); - registerMethod(L, "House", "getExitPosition", HouseFunctions::luaHouseGetExitPosition); - registerMethod(L, "House", "getRent", HouseFunctions::luaHouseGetRent); - registerMethod(L, "House", "getPrice", HouseFunctions::luaHouseGetPrice); - - registerMethod(L, "House", "getOwnerGuid", HouseFunctions::luaHouseGetOwnerGuid); - registerMethod(L, "House", "setHouseOwner", HouseFunctions::luaHouseSetHouseOwner); - registerMethod(L, "House", "setNewOwnerGuid", HouseFunctions::luaHouseSetNewOwnerGuid); - registerMethod(L, "House", "hasItemOnTile", HouseFunctions::luaHouseHasItemOnTile); - registerMethod(L, "House", "hasNewOwnership", HouseFunctions::luaHouseHasNewOwnership); - registerMethod(L, "House", "startTrade", HouseFunctions::luaHouseStartTrade); - - registerMethod(L, "House", "getBeds", HouseFunctions::luaHouseGetBeds); - registerMethod(L, "House", "getBedCount", HouseFunctions::luaHouseGetBedCount); - - registerMethod(L, "House", "getDoors", HouseFunctions::luaHouseGetDoors); - registerMethod(L, "House", "getDoorCount", HouseFunctions::luaHouseGetDoorCount); - registerMethod(L, "House", "getDoorIdByPosition", HouseFunctions::luaHouseGetDoorIdByPosition); - - registerMethod(L, "House", "getTiles", HouseFunctions::luaHouseGetTiles); - registerMethod(L, "House", "getItems", HouseFunctions::luaHouseGetItems); - registerMethod(L, "House", "getTileCount", HouseFunctions::luaHouseGetTileCount); - - registerMethod(L, "House", "canEditAccessList", HouseFunctions::luaHouseCanEditAccessList); - registerMethod(L, "House", "getAccessList", HouseFunctions::luaHouseGetAccessList); - registerMethod(L, "House", "setAccessList", HouseFunctions::luaHouseSetAccessList); - - registerMethod(L, "House", "kickPlayer", HouseFunctions::luaHouseKickPlayer); - registerMethod(L, "House", "isInvited", HouseFunctions::luaHouseIsInvited); - } + static void init(lua_State* L); private: static int luaHouseCreate(lua_State* L); diff --git a/src/lua/functions/map/map_functions.hpp b/src/lua/functions/map/map_functions.hpp index 43b025c9155..c89ee760d39 100644 --- a/src/lua/functions/map/map_functions.hpp +++ b/src/lua/functions/map/map_functions.hpp @@ -18,6 +18,12 @@ class MapFunctions final : LuaScriptInterface { public: + explicit MapFunctions(lua_State* L) : + LuaScriptInterface("MapFunctions") { + init(L); + } + ~MapFunctions() override = default; + static void init(lua_State* L) { HouseFunctions::init(L); PositionFunctions::init(L); @@ -25,6 +31,4 @@ class MapFunctions final : LuaScriptInterface { TileFunctions::init(L); TownFunctions::init(L); } - -private: }; diff --git a/src/lua/functions/map/position_functions.cpp b/src/lua/functions/map/position_functions.cpp index 06dc2219965..a9de71fde2b 100644 --- a/src/lua/functions/map/position_functions.cpp +++ b/src/lua/functions/map/position_functions.cpp @@ -7,30 +7,57 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/map/position_functions.hpp" + +#include "config/configmanager.hpp" +#include "creatures/creature.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" #include "game/movement/position.hpp" -#include "lua/functions/map/position_functions.hpp" -#include "map/spectators.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void PositionFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Position", "", PositionFunctions::luaPositionCreate); + Lua::registerMetaMethod(L, "Position", "__add", PositionFunctions::luaPositionAdd); + Lua::registerMetaMethod(L, "Position", "__sub", PositionFunctions::luaPositionSub); + Lua::registerMetaMethod(L, "Position", "__eq", PositionFunctions::luaPositionCompare); + + Lua::registerMethod(L, "Position", "getDistance", PositionFunctions::luaPositionGetDistance); + Lua::registerMethod(L, "Position", "getPathTo", PositionFunctions::luaPositionGetPathTo); + Lua::registerMethod(L, "Position", "isSightClear", PositionFunctions::luaPositionIsSightClear); + + Lua::registerMethod(L, "Position", "getTile", PositionFunctions::luaPositionGetTile); + Lua::registerMethod(L, "Position", "getZones", PositionFunctions::luaPositionGetZones); + + Lua::registerMethod(L, "Position", "sendMagicEffect", PositionFunctions::luaPositionSendMagicEffect); + Lua::registerMethod(L, "Position", "removeMagicEffect", PositionFunctions::luaPositionRemoveMagicEffect); + Lua::registerMethod(L, "Position", "sendDistanceEffect", PositionFunctions::luaPositionSendDistanceEffect); + + Lua::registerMethod(L, "Position", "sendSingleSoundEffect", PositionFunctions::luaPositionSendSingleSoundEffect); + Lua::registerMethod(L, "Position", "sendDoubleSoundEffect", PositionFunctions::luaPositionSendDoubleSoundEffect); + + Lua::registerMethod(L, "Position", "toString", PositionFunctions::luaPositionToString); +} int PositionFunctions::luaPositionCreate(lua_State* L) { // Position([x = 0[, y = 0[, z = 0[, stackpos = 0]]]]) // Position([position]) if (lua_gettop(L) <= 1) { - pushPosition(L, Position()); + Lua::pushPosition(L, Position()); return 1; } int32_t stackpos; - if (isTable(L, 2)) { - const Position &position = getPosition(L, 2, stackpos); - pushPosition(L, position, stackpos); + if (Lua::isTable(L, 2)) { + const Position &position = Lua::getPosition(L, 2, stackpos); + Lua::pushPosition(L, position, stackpos); } else { - uint16_t x = getNumber<uint16_t>(L, 2, 0); - uint16_t y = getNumber<uint16_t>(L, 3, 0); - uint8_t z = getNumber<uint8_t>(L, 4, 0); - stackpos = getNumber<int32_t>(L, 5, 0); + const auto x = Lua::getNumber<uint16_t>(L, 2, 0); + const auto y = Lua::getNumber<uint16_t>(L, 3, 0); + const auto z = Lua::getNumber<uint8_t>(L, 4, 0); + stackpos = Lua::getNumber<int32_t>(L, 5, 0); - pushPosition(L, Position(x, y, z), stackpos); + Lua::pushPosition(L, Position(x, y, z), stackpos); } return 1; } @@ -38,107 +65,107 @@ int PositionFunctions::luaPositionCreate(lua_State* L) { int PositionFunctions::luaPositionAdd(lua_State* L) { // positionValue = position + positionEx int32_t stackpos; - const Position &position = getPosition(L, 1, stackpos); + const Position &position = Lua::getPosition(L, 1, stackpos); Position positionEx; if (stackpos == 0) { - positionEx = getPosition(L, 2, stackpos); + positionEx = Lua::getPosition(L, 2, stackpos); } else { - positionEx = getPosition(L, 2); + positionEx = Lua::getPosition(L, 2); } - pushPosition(L, position + positionEx, stackpos); + Lua::pushPosition(L, position + positionEx, stackpos); return 1; } int PositionFunctions::luaPositionSub(lua_State* L) { // positionValue = position - positionEx int32_t stackpos; - const Position &position = getPosition(L, 1, stackpos); + const Position &position = Lua::getPosition(L, 1, stackpos); Position positionEx; if (stackpos == 0) { - positionEx = getPosition(L, 2, stackpos); + positionEx = Lua::getPosition(L, 2, stackpos); } else { - positionEx = getPosition(L, 2); + positionEx = Lua::getPosition(L, 2); } - pushPosition(L, position - positionEx, stackpos); + Lua::pushPosition(L, position - positionEx, stackpos); return 1; } int PositionFunctions::luaPositionCompare(lua_State* L) { // position == positionEx - const Position &positionEx = getPosition(L, 2); - const Position &position = getPosition(L, 1); - pushBoolean(L, position == positionEx); + const Position &positionEx = Lua::getPosition(L, 2); + const Position &position = Lua::getPosition(L, 1); + Lua::pushBoolean(L, position == positionEx); return 1; } int PositionFunctions::luaPositionGetDistance(lua_State* L) { // position:getDistance(positionEx) - const Position &positionEx = getPosition(L, 2); - const Position &position = getPosition(L, 1); + const Position &positionEx = Lua::getPosition(L, 2); + const Position &position = Lua::getPosition(L, 1); lua_pushnumber(L, std::max<int32_t>(std::max<int32_t>(std::abs(Position::getDistanceX(position, positionEx)), std::abs(Position::getDistanceY(position, positionEx))), std::abs(Position::getDistanceZ(position, positionEx)))); return 1; } int PositionFunctions::luaPositionGetPathTo(lua_State* L) { // position:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) - const Position &pos = getPosition(L, 1); - const Position &position = getPosition(L, 2); + const Position &pos = Lua::getPosition(L, 1); + const Position &position = Lua::getPosition(L, 2); FindPathParams fpp; - fpp.minTargetDist = getNumber<int32_t>(L, 3, 0); - fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1); - fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch); - fpp.clearSight = getBoolean(L, 6, fpp.clearSight); - fpp.maxSearchDist = getNumber<int32_t>(L, 7, fpp.maxSearchDist); + fpp.minTargetDist = Lua::getNumber<int32_t>(L, 3, 0); + fpp.maxTargetDist = Lua::getNumber<int32_t>(L, 4, 1); + fpp.fullPathSearch = Lua::getBoolean(L, 5, fpp.fullPathSearch); + fpp.clearSight = Lua::getBoolean(L, 6, fpp.clearSight); + fpp.maxSearchDist = Lua::getNumber<int32_t>(L, 7, fpp.maxSearchDist); std::vector<Direction> dirList; if (g_game().map.getPathMatching(pos, dirList, FrozenPathingConditionCall(position), fpp)) { lua_newtable(L); int index = 0; - for (Direction dir : dirList) { + for (const Direction dir : dirList) { lua_pushnumber(L, dir); lua_rawseti(L, -2, ++index); } } else { - pushBoolean(L, false); + Lua::pushBoolean(L, false); } return 1; } int PositionFunctions::luaPositionIsSightClear(lua_State* L) { // position:isSightClear(positionEx[, sameFloor = true]) - bool sameFloor = getBoolean(L, 3, true); - const Position &positionEx = getPosition(L, 2); - const Position &position = getPosition(L, 1); - pushBoolean(L, g_game().isSightClear(position, positionEx, sameFloor)); + const bool sameFloor = Lua::getBoolean(L, 3, true); + const Position &positionEx = Lua::getPosition(L, 2); + const Position &position = Lua::getPosition(L, 1); + Lua::pushBoolean(L, g_game().isSightClear(position, positionEx, sameFloor)); return 1; } int PositionFunctions::luaPositionGetTile(lua_State* L) { // position:getTile() - const Position &position = getPosition(L, 1); - pushUserdata(L, g_game().map.getTile(position)); + const Position &position = Lua::getPosition(L, 1); + Lua::pushUserdata(L, g_game().map.getTile(position)); return 1; } int PositionFunctions::luaPositionGetZones(lua_State* L) { // position:getZones() - const Position &position = getPosition(L, 1); - auto tile = g_game().map.getTile(position); + const Position &position = Lua::getPosition(L, 1); + const auto &tile = g_game().map.getTile(position); if (tile == nullptr) { lua_pushnil(L); return 1; } int index = 0; - for (auto zone : tile->getZones()) { + for (const auto &zone : tile->getZones()) { index++; - pushUserdata<Zone>(L, zone); - setMetatable(L, -1, "Zone"); + Lua::pushUserdata<Zone>(L, zone); + Lua::setMetatable(L, -1, "Zone"); lua_rawseti(L, -2, index); } return 1; @@ -148,30 +175,30 @@ int PositionFunctions::luaPositionSendMagicEffect(lua_State* L) { // position:sendMagicEffect(magicEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 3) { - const auto &player = getPlayer(L, 3); + const auto &player = Lua::getPlayer(L, 3); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } spectators.emplace_back(player); } - MagicEffectClasses magicEffect = getNumber<MagicEffectClasses>(L, 2); + MagicEffectClasses magicEffect = Lua::getNumber<MagicEffectClasses>(L, 2); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && !g_game().isMagicEffectRegistered(magicEffect)) { g_logger().warn("[PositionFunctions::luaPositionSendMagicEffect] An unregistered magic effect type with id '{}' was blocked to prevent client crash.", fmt::underlying(magicEffect)); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - const Position &position = getPosition(L, 1); + const Position &position = Lua::getPosition(L, 1); if (!spectators.empty()) { Game::addMagicEffect(spectators, position, magicEffect); } else { g_game().addMagicEffect(position, magicEffect); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -179,30 +206,30 @@ int PositionFunctions::luaPositionRemoveMagicEffect(lua_State* L) { // position:removeMagicEffect(magicEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 3) { - const auto &player = getPlayer(L, 3); + const auto &player = Lua::getPlayer(L, 3); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } spectators.emplace_back(player); } - MagicEffectClasses magicEffect = getNumber<MagicEffectClasses>(L, 2); + MagicEffectClasses magicEffect = Lua::getNumber<MagicEffectClasses>(L, 2); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && !g_game().isMagicEffectRegistered(magicEffect)) { g_logger().warn("[PositionFunctions::luaPositionRemoveMagicEffect] An unregistered magic effect type with id '{}' was blocked to prevent client crash.", fmt::underlying(magicEffect)); - pushBoolean(L, false); + Lua::pushBoolean(L, false); return 1; } - const Position &position = getPosition(L, 1); + const Position &position = Lua::getPosition(L, 1); if (!spectators.empty()) { Game::removeMagicEffect(spectators, position, magicEffect); } else { g_game().removeMagicEffect(position, magicEffect); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } @@ -210,18 +237,18 @@ int PositionFunctions::luaPositionSendDistanceEffect(lua_State* L) { // position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 4) { - const auto &player = getPlayer(L, 4); + const auto &player = Lua::getPlayer(L, 4); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + Lua::reportErrorFunc(Lua::getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } spectators.emplace_back(player); } - ShootType_t distanceEffect = getNumber<ShootType_t>(L, 3); - const Position &positionEx = getPosition(L, 2); - const Position &position = getPosition(L, 1); + const ShootType_t distanceEffect = Lua::getNumber<ShootType_t>(L, 3); + const Position &positionEx = Lua::getPosition(L, 2); + const Position &position = Lua::getPosition(L, 1); if (g_configManager().getBoolean(WARN_UNSAFE_SCRIPTS) && !g_game().isDistanceEffectRegistered(distanceEffect)) { g_logger().warn("[PositionFunctions::luaPositionSendDistanceEffect] An unregistered distance effect type with id '{}' was blocked to prevent client crash.", fmt::underlying(distanceEffect)); return 1; @@ -233,36 +260,36 @@ int PositionFunctions::luaPositionSendDistanceEffect(lua_State* L) { g_game().addDistanceEffect(position, positionEx, distanceEffect); } - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PositionFunctions::luaPositionSendSingleSoundEffect(lua_State* L) { // position:sendSingleSoundEffect(soundId[, actor = nullptr]) - const Position &position = getPosition(L, 1); - SoundEffect_t soundEffect = getNumber<SoundEffect_t>(L, 2); - std::shared_ptr<Creature> actor = getCreature(L, 3); + const Position &position = Lua::getPosition(L, 1); + const SoundEffect_t soundEffect = Lua::getNumber<SoundEffect_t>(L, 2); + const auto actor = Lua::getCreature(L, 3); g_game().sendSingleSoundEffect(position, soundEffect, actor); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PositionFunctions::luaPositionSendDoubleSoundEffect(lua_State* L) { // position:sendDoubleSoundEffect(mainSoundId, secondarySoundId[, actor = nullptr]) - const Position &position = getPosition(L, 1); - SoundEffect_t mainSoundEffect = getNumber<SoundEffect_t>(L, 2); - SoundEffect_t secondarySoundEffect = getNumber<SoundEffect_t>(L, 3); - std::shared_ptr<Creature> actor = getCreature(L, 4); + const Position &position = Lua::getPosition(L, 1); + const SoundEffect_t mainSoundEffect = Lua::getNumber<SoundEffect_t>(L, 2); + const SoundEffect_t secondarySoundEffect = Lua::getNumber<SoundEffect_t>(L, 3); + const auto &actor = Lua::getCreature(L, 4); g_game().sendDoubleSoundEffect(position, mainSoundEffect, secondarySoundEffect, actor); - pushBoolean(L, true); + Lua::pushBoolean(L, true); return 1; } int PositionFunctions::luaPositionToString(lua_State* L) { // position:toString() - const Position &position = getPosition(L, 1); - pushString(L, position.toString()); + const Position &position = Lua::getPosition(L, 1); + Lua::pushString(L, position.toString()); return 1; } diff --git a/src/lua/functions/map/position_functions.hpp b/src/lua/functions/map/position_functions.hpp index 095ec0667c7..eb864a5417f 100644 --- a/src/lua/functions/map/position_functions.hpp +++ b/src/lua/functions/map/position_functions.hpp @@ -9,32 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class PositionFunctions final : LuaScriptInterface { +class PositionFunctions { public: - static void init(lua_State* L) { - registerClass(L, "Position", "", PositionFunctions::luaPositionCreate); - registerMetaMethod(L, "Position", "__add", PositionFunctions::luaPositionAdd); - registerMetaMethod(L, "Position", "__sub", PositionFunctions::luaPositionSub); - registerMetaMethod(L, "Position", "__eq", PositionFunctions::luaPositionCompare); - - registerMethod(L, "Position", "getDistance", PositionFunctions::luaPositionGetDistance); - registerMethod(L, "Position", "getPathTo", PositionFunctions::luaPositionGetPathTo); - registerMethod(L, "Position", "isSightClear", PositionFunctions::luaPositionIsSightClear); - - registerMethod(L, "Position", "getTile", PositionFunctions::luaPositionGetTile); - registerMethod(L, "Position", "getZones", PositionFunctions::luaPositionGetZones); - - registerMethod(L, "Position", "sendMagicEffect", PositionFunctions::luaPositionSendMagicEffect); - registerMethod(L, "Position", "removeMagicEffect", PositionFunctions::luaPositionRemoveMagicEffect); - registerMethod(L, "Position", "sendDistanceEffect", PositionFunctions::luaPositionSendDistanceEffect); - - registerMethod(L, "Position", "sendSingleSoundEffect", PositionFunctions::luaPositionSendSingleSoundEffect); - registerMethod(L, "Position", "sendDoubleSoundEffect", PositionFunctions::luaPositionSendDoubleSoundEffect); - - registerMethod(L, "Position", "toString", PositionFunctions::luaPositionToString); - } + static void init(lua_State* L); private: static int luaPositionCreate(lua_State* L); diff --git a/src/lua/functions/map/teleport_functions.cpp b/src/lua/functions/map/teleport_functions.cpp index 5a5a25a20e6..c3e6f60effc 100644 --- a/src/lua/functions/map/teleport_functions.cpp +++ b/src/lua/functions/map/teleport_functions.cpp @@ -7,19 +7,29 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/functions/map/teleport_functions.hpp" + #include "game/movement/teleport.hpp" #include "items/item.hpp" -#include "lua/functions/map/teleport_functions.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void TeleportFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Teleport", "Item", TeleportFunctions::luaTeleportCreate); + Lua::registerMetaMethod(L, "Teleport", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Teleport", "getDestination", TeleportFunctions::luaTeleportGetDestination); + Lua::registerMethod(L, "Teleport", "setDestination", TeleportFunctions::luaTeleportSetDestination); +} // Teleport int TeleportFunctions::luaTeleportCreate(lua_State* L) { // Teleport(uid) - uint32_t id = getNumber<uint32_t>(L, 2); + const uint32_t id = Lua::getNumber<uint32_t>(L, 2); - std::shared_ptr<Item> item = getScriptEnv()->getItemByUID(id); + const auto &item = Lua::getScriptEnv()->getItemByUID(id); if (item && item->getTeleport()) { - pushUserdata(L, item); - setMetatable(L, -1, "Teleport"); + Lua::pushUserdata(L, item); + Lua::setMetatable(L, -1, "Teleport"); } else { lua_pushnil(L); } @@ -28,9 +38,9 @@ int TeleportFunctions::luaTeleportCreate(lua_State* L) { int TeleportFunctions::luaTeleportGetDestination(lua_State* L) { // teleport:getDestination() - std::shared_ptr<Teleport> teleport = getUserdataShared<Teleport>(L, 1); + const auto &teleport = Lua::getUserdataShared<Teleport>(L, 1); if (teleport) { - pushPosition(L, teleport->getDestPos()); + Lua::pushPosition(L, teleport->getDestPos()); } else { lua_pushnil(L); } @@ -39,10 +49,10 @@ int TeleportFunctions::luaTeleportGetDestination(lua_State* L) { int TeleportFunctions::luaTeleportSetDestination(lua_State* L) { // teleport:setDestination(position) - std::shared_ptr<Teleport> teleport = getUserdataShared<Teleport>(L, 1); + const auto &teleport = Lua::getUserdataShared<Teleport>(L, 1); if (teleport) { - teleport->setDestPos(getPosition(L, 2)); - pushBoolean(L, true); + teleport->setDestPos(Lua::getPosition(L, 2)); + Lua::pushBoolean(L, true); } else { lua_pushnil(L); } diff --git a/src/lua/functions/map/teleport_functions.hpp b/src/lua/functions/map/teleport_functions.hpp index 152cf8f0d9e..636590c1491 100644 --- a/src/lua/functions/map/teleport_functions.hpp +++ b/src/lua/functions/map/teleport_functions.hpp @@ -9,17 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class TeleportFunctions final : LuaScriptInterface { +class TeleportFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Teleport", "Item", TeleportFunctions::luaTeleportCreate); - registerMetaMethod(L, "Teleport", "__eq", TeleportFunctions::luaUserdataCompare); - - registerMethod(L, "Teleport", "getDestination", TeleportFunctions::luaTeleportGetDestination); - registerMethod(L, "Teleport", "setDestination", TeleportFunctions::luaTeleportSetDestination); - } + static void init(lua_State* L); private: static int luaTeleportCreate(lua_State* L); diff --git a/src/lua/functions/map/tile_functions.cpp b/src/lua/functions/map/tile_functions.cpp index 8ff44064079..c39d96348bd 100644 --- a/src/lua/functions/map/tile_functions.cpp +++ b/src/lua/functions/map/tile_functions.cpp @@ -7,25 +7,73 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" #include "lua/functions/map/tile_functions.hpp" +#include "creatures/combat/combat.hpp" +#include "game/game.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void TileFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Tile", "", TileFunctions::luaTileCreate); + Lua::registerMetaMethod(L, "Tile", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Tile", "getPosition", TileFunctions::luaTileGetPosition); + Lua::registerMethod(L, "Tile", "getGround", TileFunctions::luaTileGetGround); + Lua::registerMethod(L, "Tile", "getThing", TileFunctions::luaTileGetThing); + Lua::registerMethod(L, "Tile", "getThingCount", TileFunctions::luaTileGetThingCount); + Lua::registerMethod(L, "Tile", "getTopVisibleThing", TileFunctions::luaTileGetTopVisibleThing); + + Lua::registerMethod(L, "Tile", "getTopTopItem", TileFunctions::luaTileGetTopTopItem); + Lua::registerMethod(L, "Tile", "getTopDownItem", TileFunctions::luaTileGetTopDownItem); + Lua::registerMethod(L, "Tile", "getFieldItem", TileFunctions::luaTileGetFieldItem); + + Lua::registerMethod(L, "Tile", "getItemById", TileFunctions::luaTileGetItemById); + Lua::registerMethod(L, "Tile", "getItemByType", TileFunctions::luaTileGetItemByType); + Lua::registerMethod(L, "Tile", "getItemByTopOrder", TileFunctions::luaTileGetItemByTopOrder); + Lua::registerMethod(L, "Tile", "getItemCountById", TileFunctions::luaTileGetItemCountById); + + Lua::registerMethod(L, "Tile", "getBottomCreature", TileFunctions::luaTileGetBottomCreature); + Lua::registerMethod(L, "Tile", "getTopCreature", TileFunctions::luaTileGetTopCreature); + Lua::registerMethod(L, "Tile", "getBottomVisibleCreature", TileFunctions::luaTileGetBottomVisibleCreature); + Lua::registerMethod(L, "Tile", "getTopVisibleCreature", TileFunctions::luaTileGetTopVisibleCreature); + + Lua::registerMethod(L, "Tile", "getItems", TileFunctions::luaTileGetItems); + Lua::registerMethod(L, "Tile", "getItemCount", TileFunctions::luaTileGetItemCount); + Lua::registerMethod(L, "Tile", "getDownItemCount", TileFunctions::luaTileGetDownItemCount); + Lua::registerMethod(L, "Tile", "getTopItemCount", TileFunctions::luaTileGetTopItemCount); + + Lua::registerMethod(L, "Tile", "getCreatures", TileFunctions::luaTileGetCreatures); + Lua::registerMethod(L, "Tile", "getCreatureCount", TileFunctions::luaTileGetCreatureCount); + + Lua::registerMethod(L, "Tile", "getThingIndex", TileFunctions::luaTileGetThingIndex); + + Lua::registerMethod(L, "Tile", "hasProperty", TileFunctions::luaTileHasProperty); + Lua::registerMethod(L, "Tile", "hasFlag", TileFunctions::luaTileHasFlag); + + Lua::registerMethod(L, "Tile", "queryAdd", TileFunctions::luaTileQueryAdd); + Lua::registerMethod(L, "Tile", "addItem", TileFunctions::luaTileAddItem); + Lua::registerMethod(L, "Tile", "addItemEx", TileFunctions::luaTileAddItemEx); + + Lua::registerMethod(L, "Tile", "getHouse", TileFunctions::luaTileGetHouse); + Lua::registerMethod(L, "Tile", "sweep", TileFunctions::luaTileSweep); +} + int TileFunctions::luaTileCreate(lua_State* L) { // Tile(x, y, z) // Tile(position) std::shared_ptr<Tile> tile; - if (isTable(L, 2)) { - tile = g_game().map.getTile(getPosition(L, 2)); + if (Lua::isTable(L, 2)) { + tile = g_game().map.getTile(Lua::getPosition(L, 2)); } else { - uint8_t z = getNumber<uint8_t>(L, 4); - uint16_t y = getNumber<uint16_t>(L, 3); - uint16_t x = getNumber<uint16_t>(L, 2); + const uint8_t z = Lua::getNumber<uint8_t>(L, 4); + const uint16_t y = Lua::getNumber<uint16_t>(L, 3); + const uint16_t x = Lua::getNumber<uint16_t>(L, 2); tile = g_game().map.getTile(x, y, z); } if (tile) { - pushUserdata<Tile>(L, tile); - setMetatable(L, -1, "Tile"); + Lua::pushUserdata<Tile>(L, tile); + Lua::setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } @@ -33,10 +81,10 @@ int TileFunctions::luaTileCreate(lua_State* L) { } int TileFunctions::luaTileGetPosition(lua_State* L) { - // tile:getPosition() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + // tile:Lua::getPosition() + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (tile) { - pushPosition(L, tile->getPosition()); + Lua::pushPosition(L, tile->getPosition()); } else { lua_pushnil(L); } @@ -45,10 +93,10 @@ int TileFunctions::luaTileGetPosition(lua_State* L) { int TileFunctions::luaTileGetGround(lua_State* L) { // tile:getGround() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (tile && tile->getGround()) { - pushUserdata<Item>(L, tile->getGround()); - setItemMetatable(L, -1, tile->getGround()); + Lua::pushUserdata<Item>(L, tile->getGround()); + Lua::setItemMetatable(L, -1, tile->getGround()); } else { lua_pushnil(L); } @@ -57,25 +105,25 @@ int TileFunctions::luaTileGetGround(lua_State* L) { int TileFunctions::luaTileGetThing(lua_State* L) { // tile:getThing(index) - int32_t index = getNumber<int32_t>(L, 2); - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const int32_t index = Lua::getNumber<int32_t>(L, 2); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Thing> thing = tile->getThing(index); + const auto &thing = tile->getThing(index); if (!thing) { lua_pushnil(L); return 1; } - if (std::shared_ptr<Creature> creature = thing->getCreature()) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (std::shared_ptr<Item> item = thing->getItem()) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + if (const auto &creature = thing->getCreature()) { + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); + } else if (const auto &item = thing->getItem()) { + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -84,7 +132,7 @@ int TileFunctions::luaTileGetThing(lua_State* L) { int TileFunctions::luaTileGetThingCount(lua_State* L) { // tile:getThingCount() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (tile) { lua_pushnumber(L, tile->getThingCount()); } else { @@ -95,25 +143,25 @@ int TileFunctions::luaTileGetThingCount(lua_State* L) { int TileFunctions::luaTileGetTopVisibleThing(lua_State* L) { // tile:getTopVisibleThing(creature) - std::shared_ptr<Creature> creature = getCreature(L, 2); - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &creature = Lua::getCreature(L, 2); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Thing> thing = tile->getTopVisibleThing(creature); + const auto &thing = tile->getTopVisibleThing(creature); if (!thing) { lua_pushnil(L); return 1; } - if (std::shared_ptr<Creature> visibleCreature = thing->getCreature()) { - pushUserdata<Creature>(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); - } else if (std::shared_ptr<Item> visibleItem = thing->getItem()) { - pushUserdata<Item>(L, visibleItem); - setItemMetatable(L, -1, visibleItem); + if (const auto &visibleCreature = thing->getCreature()) { + Lua::pushUserdata<Creature>(L, visibleCreature); + Lua::setCreatureMetatable(L, -1, visibleCreature); + } else if (const auto &visibleItem = thing->getItem()) { + Lua::pushUserdata<Item>(L, visibleItem); + Lua::setItemMetatable(L, -1, visibleItem); } else { lua_pushnil(L); } @@ -122,16 +170,16 @@ int TileFunctions::luaTileGetTopVisibleThing(lua_State* L) { int TileFunctions::luaTileGetTopTopItem(lua_State* L) { // tile:getTopTopItem() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = tile->getTopTopItem(); + const auto &item = tile->getTopTopItem(); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -140,16 +188,16 @@ int TileFunctions::luaTileGetTopTopItem(lua_State* L) { int TileFunctions::luaTileGetTopDownItem(lua_State* L) { // tile:getTopDownItem() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = tile->getTopDownItem(); + const auto &item = tile->getTopDownItem(); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -158,16 +206,16 @@ int TileFunctions::luaTileGetTopDownItem(lua_State* L) { int TileFunctions::luaTileGetFieldItem(lua_State* L) { // tile:getFieldItem() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Item> item = tile->getFieldItem(); + const auto &item = tile->getFieldItem(); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -176,28 +224,28 @@ int TileFunctions::luaTileGetFieldItem(lua_State* L) { int TileFunctions::luaTileGetItemById(lua_State* L) { // tile:getItemById(itemId[, subType = -1]) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - int32_t subType = getNumber<int32_t>(L, 3, -1); + const auto subType = Lua::getNumber<int32_t>(L, 3, -1); - std::shared_ptr<Item> item = g_game().findItemOfType(tile, itemId, false, subType); + const auto &item = g_game().findItemOfType(tile, itemId, false, subType); if (item) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); } @@ -206,7 +254,7 @@ int TileFunctions::luaTileGetItemById(lua_State* L) { int TileFunctions::luaTileGetItemByType(lua_State* L) { // tile:getItemByType(itemType) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -214,7 +262,7 @@ int TileFunctions::luaTileGetItemByType(lua_State* L) { bool found; - ItemTypes_t itemType = getNumber<ItemTypes_t>(L, 2); + const ItemTypes_t itemType = Lua::getNumber<ItemTypes_t>(L, 2); switch (itemType) { case ITEM_TYPE_TELEPORT: found = tile->hasFlag(TILESTATE_TELEPORT); @@ -244,11 +292,11 @@ int TileFunctions::luaTileGetItemByType(lua_State* L) { return 1; } - if (std::shared_ptr<Item> item = tile->getGround()) { + if (const auto &item = tile->getGround()) { const ItemType &it = Item::items[item->getID()]; if (it.type == itemType) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); return 1; } } @@ -257,8 +305,8 @@ int TileFunctions::luaTileGetItemByType(lua_State* L) { for (auto &item : *items) { const ItemType &it = Item::items[item->getID()]; if (it.type == itemType) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); return 1; } } @@ -270,40 +318,40 @@ int TileFunctions::luaTileGetItemByType(lua_State* L) { int TileFunctions::luaTileGetItemByTopOrder(lua_State* L) { // tile:getItemByTopOrder(topOrder) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - int32_t topOrder = getNumber<int32_t>(L, 2); + const int32_t topOrder = Lua::getNumber<int32_t>(L, 2); - std::shared_ptr<Item> item = tile->getItemByTopOrder(topOrder); + const auto &item = tile->getItemByTopOrder(topOrder); if (!item) { lua_pushnil(L); return 1; } - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); return 1; } int TileFunctions::luaTileGetItemCountById(lua_State* L) { // tile:getItemCountById(itemId[, subType = -1]) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - int32_t subType = getNumber<int32_t>(L, 3, -1); + const auto subType = Lua::getNumber<int32_t>(L, 3, -1); uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; @@ -316,60 +364,60 @@ int TileFunctions::luaTileGetItemCountById(lua_State* L) { int TileFunctions::luaTileGetBottomCreature(lua_State* L) { // tile:getBottomCreature() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = tile->getBottomCreature(); + const auto &creature = tile->getBottomCreature(); if (!creature) { lua_pushnil(L); return 1; } - pushUserdata<const Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<const Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); return 1; } int TileFunctions::luaTileGetTopCreature(lua_State* L) { // tile:getTopCreature() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = tile->getTopCreature(); + const auto &creature = tile->getTopCreature(); if (!creature) { lua_pushnil(L); return 1; } - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); return 1; } int TileFunctions::luaTileGetBottomVisibleCreature(lua_State* L) { // tile:getBottomVisibleCreature(creature) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &creature = Lua::getCreature(L, 2); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> visibleCreature = tile->getBottomVisibleCreature(creature); + const auto &visibleCreature = tile->getBottomVisibleCreature(creature); if (visibleCreature) { - pushUserdata<const Creature>(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); + Lua::pushUserdata<const Creature>(L, visibleCreature); + Lua::setCreatureMetatable(L, -1, visibleCreature); } else { lua_pushnil(L); } @@ -378,22 +426,22 @@ int TileFunctions::luaTileGetBottomVisibleCreature(lua_State* L) { int TileFunctions::luaTileGetTopVisibleCreature(lua_State* L) { // tile:getTopVisibleCreature(creature) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> creature = getCreature(L, 2); + const auto &creature = Lua::getCreature(L, 2); if (!creature) { lua_pushnil(L); return 1; } - std::shared_ptr<Creature> visibleCreature = tile->getTopVisibleCreature(creature); + const auto &visibleCreature = tile->getTopVisibleCreature(creature); if (visibleCreature) { - pushUserdata<Creature>(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); + Lua::pushUserdata<Creature>(L, visibleCreature); + Lua::setCreatureMetatable(L, -1, visibleCreature); } else { lua_pushnil(L); } @@ -402,7 +450,7 @@ int TileFunctions::luaTileGetTopVisibleCreature(lua_State* L) { int TileFunctions::luaTileGetItems(lua_State* L) { // tile:getItems() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -418,8 +466,8 @@ int TileFunctions::luaTileGetItems(lua_State* L) { int index = 0; for (auto &item : *itemVector) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); lua_rawseti(L, -2, ++index); } return 1; @@ -427,7 +475,7 @@ int TileFunctions::luaTileGetItems(lua_State* L) { int TileFunctions::luaTileGetItemCount(lua_State* L) { // tile:getItemCount() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -439,7 +487,7 @@ int TileFunctions::luaTileGetItemCount(lua_State* L) { int TileFunctions::luaTileGetDownItemCount(lua_State* L) { // tile:getDownItemCount() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (tile) { lua_pushnumber(L, tile->getDownItemCount()); } else { @@ -450,7 +498,7 @@ int TileFunctions::luaTileGetDownItemCount(lua_State* L) { int TileFunctions::luaTileGetTopItemCount(lua_State* L) { // tile:getTopItemCount() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -462,7 +510,7 @@ int TileFunctions::luaTileGetTopItemCount(lua_State* L) { int TileFunctions::luaTileGetCreatures(lua_State* L) { // tile:getCreatures() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -478,8 +526,8 @@ int TileFunctions::luaTileGetCreatures(lua_State* L) { int index = 0; for (auto &creature : *creatureVector) { - pushUserdata<Creature>(L, creature); - setCreatureMetatable(L, -1, creature); + Lua::pushUserdata<Creature>(L, creature); + Lua::setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; @@ -487,7 +535,7 @@ int TileFunctions::luaTileGetCreatures(lua_State* L) { int TileFunctions::luaTileGetCreatureCount(lua_State* L) { // tile:getCreatureCount() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -499,7 +547,7 @@ int TileFunctions::luaTileGetCreatureCount(lua_State* L) { int TileFunctions::luaTileHasProperty(lua_State* L) { // tile:hasProperty(property[, item]) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; @@ -507,29 +555,29 @@ int TileFunctions::luaTileHasProperty(lua_State* L) { std::shared_ptr<Item> item; if (lua_gettop(L) >= 3) { - item = getUserdataShared<Item>(L, 3); + item = Lua::getUserdataShared<Item>(L, 3); } else { item = nullptr; } - ItemProperty property = getNumber<ItemProperty>(L, 2); + ItemProperty property = Lua::getNumber<ItemProperty>(L, 2); if (item) { - pushBoolean(L, tile->hasProperty(item, property)); + Lua::pushBoolean(L, tile->hasProperty(item, property)); } else { - pushBoolean(L, tile->hasProperty(property)); + Lua::pushBoolean(L, tile->hasProperty(property)); } return 1; } int TileFunctions::luaTileGetThingIndex(lua_State* L) { // tile:getThingIndex(thing) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Thing> thing = getThing(L, 2); + const auto &thing = Lua::getThing(L, 2); if (thing) { lua_pushnumber(L, tile->getThingIndex(thing)); } else { @@ -540,10 +588,10 @@ int TileFunctions::luaTileGetThingIndex(lua_State* L) { int TileFunctions::luaTileHasFlag(lua_State* L) { // tile:hasFlag(flag) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (tile) { - TileFlags_t flag = getNumber<TileFlags_t>(L, 2); - pushBoolean(L, tile->hasFlag(flag)); + TileFlags_t flag = Lua::getNumber<TileFlags_t>(L, 2); + Lua::pushBoolean(L, tile->hasFlag(flag)); } else { lua_pushnil(L); } @@ -552,15 +600,15 @@ int TileFunctions::luaTileHasFlag(lua_State* L) { int TileFunctions::luaTileQueryAdd(lua_State* L) { // tile:queryAdd(thing[, flags]) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - std::shared_ptr<Thing> thing = getThing(L, 2); + const auto &thing = Lua::getThing(L, 2); if (thing) { - uint32_t flags = getNumber<uint32_t>(L, 3, 0); + const auto flags = Lua::getNumber<uint32_t>(L, 3, 0); lua_pushnumber(L, tile->queryAdd(0, thing, 1, flags)); } else { lua_pushnil(L); @@ -570,37 +618,37 @@ int TileFunctions::luaTileQueryAdd(lua_State* L) { int TileFunctions::luaTileAddItem(lua_State* L) { // tile:addItem(itemId[, count/subType = 1[, flags = 0]]) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber<uint16_t>(L, 2); + if (Lua::isNumber(L, 2)) { + itemId = Lua::getNumber<uint16_t>(L, 2); } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); + itemId = Item::items.getItemIdByName(Lua::getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } - uint32_t subType = getNumber<uint32_t>(L, 3, 1); + const auto subType = Lua::getNumber<uint32_t>(L, 3, 1); - std::shared_ptr<Item> item = Item::CreateItem(itemId, std::min<uint32_t>(subType, Item::items[itemId].stackSize)); + const auto &item = Item::CreateItem(itemId, std::min<uint32_t>(subType, Item::items[itemId].stackSize)); if (!item) { lua_pushnil(L); return 1; } - uint32_t flags = getNumber<uint32_t>(L, 4, 0); + const auto flags = Lua::getNumber<uint32_t>(L, 4, 0); ReturnValue ret = g_game().internalAddItem(tile, item, INDEX_WHEREEVER, flags); if (ret == RETURNVALUE_NOERROR) { - pushUserdata<Item>(L, item); - setItemMetatable(L, -1, item); + Lua::pushUserdata<Item>(L, item); + Lua::setItemMetatable(L, -1, item); } else { lua_pushnil(L); @@ -610,25 +658,25 @@ int TileFunctions::luaTileAddItem(lua_State* L) { int TileFunctions::luaTileAddItemEx(lua_State* L) { // tile:addItemEx(item[, flags = 0]) - std::shared_ptr<Item> item = getUserdataShared<Item>(L, 2); + const auto &item = Lua::getUserdataShared<Item>(L, 2); if (!item) { lua_pushnil(L); return 1; } - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); + Lua::reportErrorFunc("Item already has a parent"); lua_pushnil(L); return 1; } - uint32_t flags = getNumber<uint32_t>(L, 3, 0); + const auto flags = Lua::getNumber<uint32_t>(L, 3, 0); ReturnValue ret = g_game().internalAddItem(tile, item, INDEX_WHEREEVER, flags); if (ret == RETURNVALUE_NOERROR) { ScriptEnvironment::removeTempItem(item); @@ -639,15 +687,15 @@ int TileFunctions::luaTileAddItemEx(lua_State* L) { int TileFunctions::luaTileGetHouse(lua_State* L) { // tile:getHouse() - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - if (std::shared_ptr<HouseTile> houseTile = std::dynamic_pointer_cast<HouseTile>(tile)) { - pushUserdata<House>(L, houseTile->getHouse()); - setMetatable(L, -1, "House"); + if (const auto &houseTile = std::dynamic_pointer_cast<HouseTile>(tile)) { + Lua::pushUserdata<House>(L, houseTile->getHouse()); + Lua::setMetatable(L, -1, "House"); } else { lua_pushnil(L); } @@ -656,18 +704,18 @@ int TileFunctions::luaTileGetHouse(lua_State* L) { int TileFunctions::luaTileSweep(lua_State* L) { // tile:sweep(actor) - std::shared_ptr<Tile> tile = getUserdataShared<Tile>(L, 1); + const auto &tile = Lua::getUserdataShared<Tile>(L, 1); if (!tile) { lua_pushnil(L); return 1; } - auto actor = getPlayer(L, 2); + const auto &actor = Lua::getPlayer(L, 2); if (!actor) { lua_pushnil(L); return 1; } - auto house = tile->getHouse(); + const auto &house = tile->getHouse(); if (!house) { g_logger().debug("TileFunctions::luaTileSweep: tile has no house"); lua_pushnil(L); @@ -680,13 +728,13 @@ int TileFunctions::luaTileSweep(lua_State* L) { return 1; } - auto houseTile = std::dynamic_pointer_cast<HouseTile>(tile); + const auto &houseTile = std::dynamic_pointer_cast<HouseTile>(tile); if (!houseTile) { g_logger().debug("TileFunctions::luaTileSweep: tile is not a house tile"); lua_pushnil(L); return 1; } - pushBoolean(L, house->transferToDepot(actor, houseTile)); + Lua::pushBoolean(L, house->transferToDepot(actor, houseTile)); return 1; } diff --git a/src/lua/functions/map/tile_functions.hpp b/src/lua/functions/map/tile_functions.hpp index 78e8c44b32c..e88b39acef8 100644 --- a/src/lua/functions/map/tile_functions.hpp +++ b/src/lua/functions/map/tile_functions.hpp @@ -9,54 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class TileFunctions final : LuaScriptInterface { +class TileFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Tile", "", TileFunctions::luaTileCreate); - registerMetaMethod(L, "Tile", "__eq", TileFunctions::luaUserdataCompare); - - registerMethod(L, "Tile", "getPosition", TileFunctions::luaTileGetPosition); - registerMethod(L, "Tile", "getGround", TileFunctions::luaTileGetGround); - registerMethod(L, "Tile", "getThing", TileFunctions::luaTileGetThing); - registerMethod(L, "Tile", "getThingCount", TileFunctions::luaTileGetThingCount); - registerMethod(L, "Tile", "getTopVisibleThing", TileFunctions::luaTileGetTopVisibleThing); - - registerMethod(L, "Tile", "getTopTopItem", TileFunctions::luaTileGetTopTopItem); - registerMethod(L, "Tile", "getTopDownItem", TileFunctions::luaTileGetTopDownItem); - registerMethod(L, "Tile", "getFieldItem", TileFunctions::luaTileGetFieldItem); - - registerMethod(L, "Tile", "getItemById", TileFunctions::luaTileGetItemById); - registerMethod(L, "Tile", "getItemByType", TileFunctions::luaTileGetItemByType); - registerMethod(L, "Tile", "getItemByTopOrder", TileFunctions::luaTileGetItemByTopOrder); - registerMethod(L, "Tile", "getItemCountById", TileFunctions::luaTileGetItemCountById); - - registerMethod(L, "Tile", "getBottomCreature", TileFunctions::luaTileGetBottomCreature); - registerMethod(L, "Tile", "getTopCreature", TileFunctions::luaTileGetTopCreature); - registerMethod(L, "Tile", "getBottomVisibleCreature", TileFunctions::luaTileGetBottomVisibleCreature); - registerMethod(L, "Tile", "getTopVisibleCreature", TileFunctions::luaTileGetTopVisibleCreature); - - registerMethod(L, "Tile", "getItems", TileFunctions::luaTileGetItems); - registerMethod(L, "Tile", "getItemCount", TileFunctions::luaTileGetItemCount); - registerMethod(L, "Tile", "getDownItemCount", TileFunctions::luaTileGetDownItemCount); - registerMethod(L, "Tile", "getTopItemCount", TileFunctions::luaTileGetTopItemCount); - - registerMethod(L, "Tile", "getCreatures", TileFunctions::luaTileGetCreatures); - registerMethod(L, "Tile", "getCreatureCount", TileFunctions::luaTileGetCreatureCount); - - registerMethod(L, "Tile", "getThingIndex", TileFunctions::luaTileGetThingIndex); - - registerMethod(L, "Tile", "hasProperty", TileFunctions::luaTileHasProperty); - registerMethod(L, "Tile", "hasFlag", TileFunctions::luaTileHasFlag); - - registerMethod(L, "Tile", "queryAdd", TileFunctions::luaTileQueryAdd); - registerMethod(L, "Tile", "addItem", TileFunctions::luaTileAddItem); - registerMethod(L, "Tile", "addItemEx", TileFunctions::luaTileAddItemEx); - - registerMethod(L, "Tile", "getHouse", TileFunctions::luaTileGetHouse); - registerMethod(L, "Tile", "sweep", TileFunctions::luaTileSweep); - } + static void init(lua_State* L); private: static int luaTileCreate(lua_State* L); diff --git a/src/lua/functions/map/town_functions.cpp b/src/lua/functions/map/town_functions.cpp index 3ccf112e772..fa77003fe77 100644 --- a/src/lua/functions/map/town_functions.cpp +++ b/src/lua/functions/map/town_functions.cpp @@ -7,24 +7,35 @@ * Website: https://docs.opentibiabr.com/ */ -#include "game/game.hpp" #include "lua/functions/map/town_functions.hpp" + +#include "game/game.hpp" #include "map/town.hpp" +#include "lua/functions/lua_functions_loader.hpp" + +void TownFunctions::init(lua_State* L) { + Lua::registerSharedClass(L, "Town", "", TownFunctions::luaTownCreate); + Lua::registerMetaMethod(L, "Town", "__eq", Lua::luaUserdataCompare); + + Lua::registerMethod(L, "Town", "getId", TownFunctions::luaTownGetId); + Lua::registerMethod(L, "Town", "getName", TownFunctions::luaTownGetName); + Lua::registerMethod(L, "Town", "getTemplePosition", TownFunctions::luaTownGetTemplePosition); +} int TownFunctions::luaTownCreate(lua_State* L) { // Town(id or name) std::shared_ptr<Town> town; - if (isNumber(L, 2)) { - town = g_game().map.towns.getTown(getNumber<uint32_t>(L, 2)); - } else if (isString(L, 2)) { - town = g_game().map.towns.getTown(getString(L, 2)); + if (Lua::isNumber(L, 2)) { + town = g_game().map.towns.getTown(Lua::getNumber<uint32_t>(L, 2)); + } else if (Lua::isString(L, 2)) { + town = g_game().map.towns.getTown(Lua::getString(L, 2)); } else { town = nullptr; } if (town) { - pushUserdata<Town>(L, town); - setMetatable(L, -1, "Town"); + Lua::pushUserdata<Town>(L, town); + Lua::setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } @@ -33,7 +44,7 @@ int TownFunctions::luaTownCreate(lua_State* L) { int TownFunctions::luaTownGetId(lua_State* L) { // town:getId() - if (const auto &town = getUserdataShared<Town>(L, 1)) { + if (const auto &town = Lua::getUserdataShared<Town>(L, 1)) { lua_pushnumber(L, town->getID()); } else { lua_pushnil(L); @@ -43,8 +54,8 @@ int TownFunctions::luaTownGetId(lua_State* L) { int TownFunctions::luaTownGetName(lua_State* L) { // town:getName() - if (const auto &town = getUserdataShared<Town>(L, 1)) { - pushString(L, town->getName()); + if (const auto &town = Lua::getUserdataShared<Town>(L, 1)) { + Lua::pushString(L, town->getName()); } else { lua_pushnil(L); } @@ -53,8 +64,8 @@ int TownFunctions::luaTownGetName(lua_State* L) { int TownFunctions::luaTownGetTemplePosition(lua_State* L) { // town:getTemplePosition() - if (const auto &town = getUserdataShared<Town>(L, 1)) { - pushPosition(L, town->getTemplePosition()); + if (const auto &town = Lua::getUserdataShared<Town>(L, 1)) { + Lua::pushPosition(L, town->getTemplePosition()); } else { lua_pushnil(L); } diff --git a/src/lua/functions/map/town_functions.hpp b/src/lua/functions/map/town_functions.hpp index 65ff991c2c9..81430daf2c4 100644 --- a/src/lua/functions/map/town_functions.hpp +++ b/src/lua/functions/map/town_functions.hpp @@ -9,22 +9,12 @@ #pragma once -#include "lua/scripts/luascript.hpp" - -class TownFunctions final : LuaScriptInterface { +class TownFunctions { public: - static void init(lua_State* L) { - registerSharedClass(L, "Town", "", TownFunctions::luaTownCreate); - registerMetaMethod(L, "Town", "__eq", TownFunctions::luaUserdataCompare); - - registerMethod(L, "Town", "getId", TownFunctions::luaTownGetId); - registerMethod(L, "Town", "getName", TownFunctions::luaTownGetName); - registerMethod(L, "Town", "getTemplePosition", TownFunctions::luaTownGetTemplePosition); - } + static void init(lua_State* L); private: static int luaTownCreate(lua_State* L); - static int luaTownGetId(lua_State* L); static int luaTownGetName(lua_State* L); static int luaTownGetTemplePosition(lua_State* L); diff --git a/src/lua/global/baseevents.cpp b/src/lua/global/baseevents.cpp index 78c1195ab28..71832291da6 100644 --- a/src/lua/global/baseevents.cpp +++ b/src/lua/global/baseevents.cpp @@ -8,7 +8,10 @@ */ #include "lua/global/baseevents.hpp" + +#include "config/configmanager.hpp" #include "lua/scripts/lua_environment.hpp" +#include "lua/scripts/luascript.hpp" #include "utils/tools.hpp" bool BaseEvents::loadFromXml() { @@ -27,10 +30,10 @@ bool BaseEvents::loadFromXml() { g_logger().warn(__FUNCTION__, scriptsName, scriptsName); } - std::string filename = basePath + scriptsName + ".xml"; + const std::string filename = basePath + scriptsName + ".xml"; pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); + const pugi::xml_parse_result result = doc.load_file(filename.c_str()); if (!result) { printXMLError(__FUNCTION__, filename, result); return false; @@ -38,8 +41,8 @@ bool BaseEvents::loadFromXml() { loaded = true; - for (auto node : doc.child(scriptsName.c_str()).children()) { - Event_ptr event = getEvent(node.name()); + for (const auto &node : doc.child(scriptsName.c_str()).children()) { + const auto &event = getEvent(node.name()); if (!event) { continue; } @@ -64,7 +67,7 @@ bool BaseEvents::loadFromXml() { } if (success) { - registerEvent(std::move(event), node); + registerEvent(event, node); } } return true; @@ -72,7 +75,7 @@ bool BaseEvents::loadFromXml() { bool BaseEvents::reload() { loaded = false; - clear(false); + clear(); return loadFromXml(); } @@ -102,7 +105,7 @@ bool Event::checkScript(const std::string &basePath, const std::string &scriptsN return false; } - int32_t id = testInterface->getEvent(getScriptEventName()); + const int32_t id = testInterface->getEvent(getScriptEventName()); if (id == -1) { g_logger().warn("[Event::checkScript] - Event " "{} not found {}", @@ -127,7 +130,7 @@ bool Event::loadScript(const std::string &scriptFile, const std::string &scriptN return false; } - int32_t id = scriptInterface->getEvent(getScriptEventName()); + const int32_t id = scriptInterface->getEvent(getScriptEventName()); if (id == -1) { g_logger().warn( "[Event::loadScript] - Event {} not found {}", @@ -150,7 +153,7 @@ bool CallBack::loadCallBack(LuaScriptInterface* interface, const std::string &na scriptInterface = interface; - int32_t id = scriptInterface->getEvent(name.c_str()); + const int32_t id = scriptInterface->getEvent(name); if (id == -1) { g_logger().warn("[{}] - Event {} not found", __FUNCTION__, name); return false; diff --git a/src/lua/global/baseevents.hpp b/src/lua/global/baseevents.hpp index 48e2d104a92..754f8a7b212 100644 --- a/src/lua/global/baseevents.hpp +++ b/src/lua/global/baseevents.hpp @@ -9,10 +9,9 @@ #pragma once -#include "lua/scripts/luascript.hpp" - +class LuaScriptInterface; class Event; -using Event_ptr = std::unique_ptr<Event>; +using Event_ptr = std::shared_ptr<Event>; /** * @brief Class that describes an event @@ -84,7 +83,7 @@ class Event { * * @return int32_t */ - int32_t getScriptId() { + int32_t getScriptId() const { return scriptId; } @@ -147,8 +146,8 @@ class BaseEvents { virtual LuaScriptInterface &getScriptInterface() = 0; virtual std::string getScriptBaseName() const = 0; virtual Event_ptr getEvent(const std::string &nodeName) = 0; - virtual bool registerEvent(Event_ptr event, const pugi::xml_node &node) = 0; - virtual void clear(bool) = 0; + virtual bool registerEvent(const Event_ptr &event, const pugi::xml_node &node) = 0; + virtual void clear() = 0; bool loaded = false; diff --git a/src/lua/global/globalevent.cpp b/src/lua/global/globalevent.cpp index 9cb24292b12..ae988a814de 100644 --- a/src/lua/global/globalevent.cpp +++ b/src/lua/global/globalevent.cpp @@ -8,13 +8,20 @@ */ #include "lua/global/globalevent.hpp" + #include "utils/tools.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" +#include "lua/scripts/scripts.hpp" +#include "lib/di/container.hpp" GlobalEvents::GlobalEvents() = default; GlobalEvents::~GlobalEvents() = default; +GlobalEvents &GlobalEvents::getInstance() { + return inject<GlobalEvents>(); +} + void GlobalEvents::clear() { // Stop events g_dispatcher().stopEvent(thinkEventId); @@ -28,9 +35,9 @@ void GlobalEvents::clear() { timerMap.clear(); } -bool GlobalEvents::registerLuaEvent(const std::shared_ptr<GlobalEvent> globalEvent) { +bool GlobalEvents::registerLuaEvent(const std::shared_ptr<GlobalEvent> &globalEvent) { if (globalEvent->getEventType() == GLOBALEVENT_TIMER) { - auto result = timerMap.emplace(globalEvent->getName(), globalEvent); + const auto result = timerMap.emplace(globalEvent->getName(), globalEvent); if (result.second) { if (timerEventId == 0) { timerEventId = g_dispatcher().scheduleEvent( @@ -40,12 +47,12 @@ bool GlobalEvents::registerLuaEvent(const std::shared_ptr<GlobalEvent> globalEve return true; } } else if (globalEvent->getEventType() != GLOBALEVENT_NONE) { - auto result = serverMap.emplace(globalEvent->getName(), globalEvent); + const auto result = serverMap.emplace(globalEvent->getName(), globalEvent); if (result.second) { return true; } } else { // think event - auto result = thinkMap.emplace(globalEvent->getName(), globalEvent); + const auto result = thinkMap.emplace(globalEvent->getName(), globalEvent); if (result.second) { if (thinkEventId == 0) { thinkEventId = g_dispatcher().scheduleEvent( @@ -73,13 +80,13 @@ void GlobalEvents::save() const { } void GlobalEvents::timer() { - time_t now = time(nullptr); + const time_t now = time(nullptr); int64_t nextScheduledTime = std::numeric_limits<int64_t>::max(); auto it = timerMap.begin(); while (it != timerMap.end()) { - const auto globalEvent = it->second; + const auto &globalEvent = it->second; int64_t nextExecutionTime = globalEvent->getNextExecution() - now; if (nextExecutionTime > 0) { @@ -114,7 +121,7 @@ void GlobalEvents::timer() { } void GlobalEvents::think() { - int64_t now = OTSYS_TIME(); + const int64_t now = OTSYS_TIME(); int64_t nextScheduledTime = std::numeric_limits<int64_t>::max(); for (const auto &[globalEventName, globalEvent] : thinkMap) { @@ -143,7 +150,7 @@ void GlobalEvents::think() { } if (nextScheduledTime != std::numeric_limits<int64_t>::max()) { - auto delay = static_cast<uint32_t>(nextScheduledTime); + const auto delay = static_cast<uint32_t>(nextScheduledTime); thinkEventId = g_dispatcher().scheduleEvent( delay, [this] { think(); }, "GlobalEvents::think" ); @@ -183,8 +190,34 @@ GlobalEventMap GlobalEvents::getEventMap(GlobalEvent_t type) { } } -GlobalEvent::GlobalEvent(LuaScriptInterface* interface) : - Script(interface) { } +GlobalEvent::GlobalEvent() = default; + +LuaScriptInterface* GlobalEvent::getScriptInterface() const { + return &g_scripts().getScriptInterface(); +} + +bool GlobalEvent::loadScriptId() { + LuaScriptInterface &luaInterface = g_scripts().getScriptInterface(); + m_scriptId = luaInterface.getEvent(); + if (m_scriptId == -1) { + g_logger().error("[MoveEvent::loadScriptId] Failed to load event. Script name: '{}', Module: '{}'", luaInterface.getLoadingScriptName(), luaInterface.getInterfaceName()); + return false; + } + + return true; +} + +int32_t GlobalEvent::getScriptId() const { + return m_scriptId; +} + +void GlobalEvent::setScriptId(int32_t newScriptId) { + m_scriptId = newScriptId; +} + +bool GlobalEvent::isLoadedScriptId() const { + return m_scriptId != 0; +} std::string GlobalEvent::getScriptTypeName() const { switch (eventType) { @@ -204,20 +237,20 @@ std::string GlobalEvent::getScriptTypeName() const { return "onSave"; default: g_logger().error("[GlobalEvent::getScriptTypeName] - Invalid event type"); - return std::string(); + return {}; } } bool GlobalEvent::executePeriodChange(LightState_t lightState, LightInfo lightInfo) const { // onPeriodChange(lightState, lightTime) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[GlobalEvent::executePeriodChange - {}] " "Call stack overflow. Too many lua script calls being nested.", getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -228,16 +261,16 @@ bool GlobalEvent::executePeriodChange(LightState_t lightState, LightInfo lightIn return getScriptInterface()->callFunction(2); } -bool GlobalEvent::executeRecord(uint32_t current, uint32_t old) { +bool GlobalEvent::executeRecord(uint32_t current, uint32_t old) const { // onRecord(current, old) - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[GlobalEvent::executeRecord - {}] " "Call stack overflow. Too many lua script calls being nested.", getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); @@ -249,14 +282,14 @@ bool GlobalEvent::executeRecord(uint32_t current, uint32_t old) { } bool GlobalEvent::executeEvent() const { - if (!getScriptInterface()->reserveScriptEnv()) { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("[GlobalEvent::executeEvent - {}] " "Call stack overflow. Too many lua script calls being nested.", getName()); return false; } - ScriptEnvironment* env = getScriptInterface()->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(getScriptId(), getScriptInterface()); lua_State* L = getScriptInterface()->getLuaState(); getScriptInterface()->pushFunction(getScriptId()); diff --git a/src/lua/global/globalevent.hpp b/src/lua/global/globalevent.hpp index 128a743b3fb..f8337cd773f 100644 --- a/src/lua/global/globalevent.hpp +++ b/src/lua/global/globalevent.hpp @@ -10,12 +10,17 @@ #pragma once #include "utils/utils_definitions.hpp" -#include "lua/scripts/scripts.hpp" +#include "lua/lua_definitions.hpp" +class LuaScriptInterface; class GlobalEvent; using GlobalEventMap = std::map<std::string, std::shared_ptr<GlobalEvent>>; -class GlobalEvents final : public Scripts { +enum LightState_t : uint8_t; + +struct LightInfo; + +class GlobalEvents { public: GlobalEvents(); ~GlobalEvents(); @@ -24,9 +29,7 @@ class GlobalEvents final : public Scripts { GlobalEvents(const GlobalEvents &) = delete; GlobalEvents &operator=(const GlobalEvents &) = delete; - static GlobalEvents &getInstance() { - return inject<GlobalEvents>(); - } + static GlobalEvents &getInstance(); void startup() const; void shutdown() const; @@ -38,22 +41,23 @@ class GlobalEvents final : public Scripts { GlobalEventMap getEventMap(GlobalEvent_t type); - bool registerLuaEvent(const std::shared_ptr<GlobalEvent> globalEvent); + bool registerLuaEvent(const std::shared_ptr<GlobalEvent> &globalEvent); void clear(); private: GlobalEventMap thinkMap, serverMap, timerMap; - uint64_t thinkEventId = 0, timerEventId = 0; + uint64_t thinkEventId = 0; + uint64_t timerEventId = 0; }; constexpr auto g_globalEvents = GlobalEvents::getInstance; -class GlobalEvent final : public Script { +class GlobalEvent { public: - explicit GlobalEvent(LuaScriptInterface* interface); + explicit GlobalEvent(); bool executePeriodChange(LightState_t lightState, LightInfo lightInfo) const; - bool executeRecord(uint32_t current, uint32_t old); + bool executeRecord(uint32_t current, uint32_t old) const; bool executeEvent() const; GlobalEvent_t getEventType() const { @@ -67,7 +71,7 @@ class GlobalEvent final : public Script { return name; } void setName(std::string eventName) { - name = eventName; + name = std::move(eventName); } uint32_t getInterval() const { return interval; @@ -83,10 +87,17 @@ class GlobalEvent final : public Script { nextExecution = time; } + std::string getScriptTypeName() const; + LuaScriptInterface* getScriptInterface() const; + bool loadScriptId(); + int32_t getScriptId() const; + void setScriptId(int32_t newScriptId); + bool isLoadedScriptId() const; + private: - GlobalEvent_t eventType = GLOBALEVENT_NONE; + int32_t m_scriptId {}; - std::string getScriptTypeName() const override; + GlobalEvent_t eventType = GLOBALEVENT_NONE; std::string name; int64_t nextExecution = 0; diff --git a/src/lua/lua_definitions.hpp b/src/lua/lua_definitions.hpp index a01f6d9db7e..fa1bdcec01a 100644 --- a/src/lua/lua_definitions.hpp +++ b/src/lua/lua_definitions.hpp @@ -57,7 +57,7 @@ enum class LuaData_t : uint8_t { ItemClassification, }; -enum CreatureEventType_t { +enum CreatureEventType_t : uint8_t { CREATURE_EVENT_NONE, CREATURE_EVENT_LOGIN, CREATURE_EVENT_LOGOUT, @@ -99,7 +99,7 @@ enum TalkActionResult_t { TALKACTION_FAILED, }; -enum GlobalEvent_t { +enum GlobalEvent_t : uint8_t { GLOBALEVENT_NONE, GLOBALEVENT_TIMER, diff --git a/src/lua/modules/modules.cpp b/src/lua/modules/modules.cpp index 04cddc43443..1e501b85c83 100644 --- a/src/lua/modules/modules.cpp +++ b/src/lua/modules/modules.cpp @@ -8,6 +8,7 @@ */ #include "lua/modules/modules.hpp" + #include "creatures/players/player.hpp" #include "game/game.hpp" @@ -16,10 +17,15 @@ Modules::Modules() : scriptInterface.initState(); } -void Modules::clear(bool) { +void Modules::clear() { // clear recvbyte list - for (auto &it : recvbyteList) { - it.second.clearEvent(); + for (const auto &[moduleId, modulePtr] : recvbyteList) { + if (moduleId == 0) { + g_logger().error("Invalid module id 0."); + continue; + } + + modulePtr->clearEvent(); } // clear lua state @@ -38,54 +44,56 @@ Event_ptr Modules::getEvent(const std::string &nodeName) { if (strcasecmp(nodeName.c_str(), "module") != 0) { return nullptr; } - return Event_ptr(new Module(&scriptInterface)); + return std::make_unique<Module>(&scriptInterface); } -bool Modules::registerEvent(Event_ptr event, const pugi::xml_node &) { - Module_ptr module { static_cast<Module*>(event.release()) }; - if (module->getEventType() == MODULE_TYPE_NONE) { +bool Modules::registerEvent(const Event_ptr &event, const pugi::xml_node &) { + const auto &modulePtr = std::dynamic_pointer_cast<Module>(event); + if (modulePtr->getEventType() == MODULE_TYPE_NONE) { g_logger().error("Trying to register event without type!"); return false; } - Module* oldModule = getEventByRecvbyte(module->getRecvbyte(), false); + const auto oldModule = getEventByRecvbyte(modulePtr->getRecvbyte(), false); if (oldModule) { - if (!oldModule->isLoaded() && oldModule->getEventType() == module->getEventType()) { - oldModule->copyEvent(module.get()); + if (!oldModule->isLoaded() && oldModule->getEventType() == modulePtr->getEventType()) { + oldModule->copyEvent(modulePtr); + return true; } return false; + } + + const auto it = recvbyteList.find(modulePtr->getRecvbyte()); + if (it != recvbyteList.end()) { + it->second = modulePtr; } else { - auto it = recvbyteList.find(module->getRecvbyte()); - if (it != recvbyteList.end()) { - it->second = *module; - } else { - recvbyteList.emplace(module->getRecvbyte(), std::move(*module)); - } - return true; + recvbyteList.try_emplace(modulePtr->getRecvbyte(), modulePtr); } + return true; } -Module* Modules::getEventByRecvbyte(uint8_t recvbyte, bool force) { - ModulesList::iterator it = recvbyteList.find(recvbyte); - if (it != recvbyteList.end()) { - if (!force || it->second.isLoaded()) { - return &it->second; - } +Module_ptr Modules::getEventByRecvbyte(uint8_t recvbyte, bool force) { + const auto it = recvbyteList.find(recvbyte); + if (it != recvbyteList.end() && (!force || it->second->isLoaded())) { + return it->second; } return nullptr; } void Modules::executeOnRecvbyte(uint32_t playerId, NetworkMessage &msg, uint8_t byte) const { - std::shared_ptr<Player> player = g_game().getPlayerByID(playerId); + const auto &player = g_game().getPlayerByID(playerId); if (!player) { return; } - for (auto &it : recvbyteList) { - Module module = it.second; - if (module.getEventType() == MODULE_TYPE_RECVBYTE && module.getRecvbyte() == byte && player->canRunModule(module.getRecvbyte())) { - player->setModuleDelay(module.getRecvbyte(), module.getDelay()); - module.executeOnRecvbyte(player, msg); + for (const auto &[moduleId, modulePtr] : recvbyteList) { + if (moduleId == 0) { + g_logger().error("Invalid module id 0."); + continue; + } + if (modulePtr->getEventType() == MODULE_TYPE_RECVBYTE && modulePtr->getRecvbyte() == byte && player->canRunModule(modulePtr->getRecvbyte())) { + player->setModuleDelay(modulePtr->getRecvbyte(), modulePtr->getDelay()); + modulePtr->executeOnRecvbyte(player, msg); return; } } @@ -97,15 +105,15 @@ Module::Module(LuaScriptInterface* interface) : bool Module::configureEvent(const pugi::xml_node &node) { delay = 0; - pugi::xml_attribute typeAttribute = node.attribute("type"); + const auto typeAttribute = node.attribute("type"); if (!typeAttribute) { g_logger().error("Missing type for module."); return false; } - std::string tmpStr = asLowerCaseString(typeAttribute.as_string()); + const auto tmpStr = asLowerCaseString(typeAttribute.as_string()); if (tmpStr == "recvbyte") { - pugi::xml_attribute byteAttribute = node.attribute("byte"); + const auto byteAttribute = node.attribute("byte"); if (!byteAttribute) { g_logger().error("Missing byte for module typed recvbyte."); return false; @@ -118,9 +126,9 @@ bool Module::configureEvent(const pugi::xml_node &node) { return false; } - pugi::xml_attribute delayAttribute = node.attribute("delay"); + const auto delayAttribute = node.attribute("delay"); if (delayAttribute) { - delay = static_cast<uint16_t>(delayAttribute.as_uint()); + delay = static_cast<int16_t>(delayAttribute.as_uint()); } loaded = true; @@ -132,15 +140,15 @@ std::string Module::getScriptEventName() const { case MODULE_TYPE_RECVBYTE: return "onRecvbyte"; default: - return std::string(); + return {}; } } -void Module::copyEvent(Module* module) { - scriptId = module->scriptId; - scriptInterface = module->scriptInterface; - scripted = module->scripted; - loaded = module->loaded; +void Module::copyEvent(const Module_ptr &modulePtr) { + scriptId = modulePtr->scriptId; + scriptInterface = modulePtr->scriptInterface; + scripted = modulePtr->scripted; + loaded = modulePtr->loaded; } void Module::clearEvent() { @@ -150,14 +158,13 @@ void Module::clearEvent() { loaded = false; } -void Module::executeOnRecvbyte(std::shared_ptr<Player> player, NetworkMessage &msg) { - // onRecvbyte(player, msg, recvbyte) - if (!scriptInterface->reserveScriptEnv()) { +void Module::executeOnRecvbyte(const std::shared_ptr<Player> &player, NetworkMessage &msg) const { + if (!LuaScriptInterface::reserveScriptEnv()) { g_logger().error("Call stack overflow. Too many lua script calls being nested {}", player->getName()); return; } - ScriptEnvironment* env = scriptInterface->getScriptEnv(); + ScriptEnvironment* env = LuaScriptInterface::getScriptEnv(); env->setScriptId(scriptId, scriptInterface); lua_State* L = scriptInterface->getLuaState(); diff --git a/src/lua/modules/modules.hpp b/src/lua/modules/modules.hpp index 6543138d515..400ced5e0b4 100644 --- a/src/lua/modules/modules.hpp +++ b/src/lua/modules/modules.hpp @@ -16,13 +16,13 @@ #include "server/network/message/networkmessage.hpp" class Module; -using Module_ptr = std::unique_ptr<Module>; +using Module_ptr = std::shared_ptr<Module>; class Module final : public Event { public: explicit Module(LuaScriptInterface* interface); - bool configureEvent(const pugi::xml_node &node) final; + bool configureEvent(const pugi::xml_node &node) override; ModuleType_t getEventType() const { return type; @@ -32,26 +32,26 @@ class Module final : public Event { } void clearEvent(); - void copyEvent(Module* creatureEvent); + void copyEvent(const Module_ptr &creatureEvent); // scripting - void executeOnRecvbyte(std::shared_ptr<Player> player, NetworkMessage &msg); + void executeOnRecvbyte(const std::shared_ptr<Player> &player, NetworkMessage &msg) const; // - uint8_t getRecvbyte() { + uint8_t getRecvbyte() const { return recvbyte; } - int16_t getDelay() { + int16_t getDelay() const { return delay; } protected: - std::string getScriptEventName() const final; + std::string getScriptEventName() const override; ModuleType_t type; - uint8_t recvbyte; - int16_t delay; + uint8_t recvbyte {}; + int16_t delay {}; bool loaded; }; @@ -68,16 +68,16 @@ class Modules final : public BaseEvents { } void executeOnRecvbyte(uint32_t playerId, NetworkMessage &msg, uint8_t byte) const; - Module* getEventByRecvbyte(uint8_t recvbyte, bool force); + Module_ptr getEventByRecvbyte(uint8_t recvbyte, bool force); protected: LuaScriptInterface &getScriptInterface() override; std::string getScriptBaseName() const override; Event_ptr getEvent(const std::string &nodeName) override; - bool registerEvent(Event_ptr event, const pugi::xml_node &node) override; - void clear(bool) override final; + bool registerEvent(const Event_ptr &event, const pugi::xml_node &node) override; + void clear() override; - typedef std::map<uint8_t, Module> ModulesList; + using ModulesList = std::map<uint8_t, Module_ptr>; ModulesList recvbyteList; LuaScriptInterface scriptInterface; diff --git a/src/lua/scripts/lua_environment.cpp b/src/lua/scripts/lua_environment.cpp index 04afd75f958..9e95beaf8da 100644 --- a/src/lua/scripts/lua_environment.cpp +++ b/src/lua/scripts/lua_environment.cpp @@ -7,14 +7,20 @@ * Website: https://docs.opentibiabr.com/ */ -#include "declarations.hpp" #include "lua/scripts/lua_environment.hpp" + +#include "declarations.hpp" #include "lua/functions/lua_functions_loader.hpp" #include "lua/scripts/script_environment.hpp" #include "lua/global/lua_timer_event_descr.hpp" +#include "lib/di/container.hpp" bool LuaEnvironment::shuttingDown = false; +LuaEnvironment &LuaEnvironment::getInstance() { + return inject<LuaEnvironment>(); +} + static const std::unique_ptr<AreaCombat> &AreaCombatNull {}; LuaEnvironment::LuaEnvironment() : @@ -42,7 +48,7 @@ lua_State* LuaEnvironment::getLuaState() { bool LuaEnvironment::initState() { luaState = luaL_newstate(); - LuaFunctionsLoader::load(luaState); + Lua::load(luaState); runningEventId = EVENT_ID_USER; return true; @@ -59,23 +65,18 @@ bool LuaEnvironment::closeState() { return false; } - for (const auto &combatEntry : combatIdMap) { - clearCombatObjects(combatEntry.first); - } - for (const auto &areaEntry : areaIdMap) { clearAreaObjects(areaEntry.first); } for (auto &timerEntry : timerEvents) { LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second); - for (int32_t parameter : timerEventDesc.parameters) { + for (const int32_t parameter : timerEventDesc.parameters) { luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); } luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); } - combatIdMap.clear(); areaIdMap.clear(); timerEvents.clear(); cacheFiles.clear(); @@ -93,33 +94,8 @@ LuaScriptInterface* LuaEnvironment::getTestInterface() { return testInterface; } -std::shared_ptr<Combat> LuaEnvironment::getCombatObject(uint32_t id) const { - auto it = combatMap.find(id); - if (it == combatMap.end()) { - return nullptr; - } - return it->second; -} - -std::shared_ptr<Combat> LuaEnvironment::createCombatObject(LuaScriptInterface* interface) { - auto combat = std::make_shared<Combat>(); - combatMap[++lastCombatId] = combat; - combatIdMap[interface].push_back(lastCombatId); - return combat; -} - -void LuaEnvironment::clearCombatObjects(LuaScriptInterface* interface) { - auto it = combatIdMap.find(interface); - if (it == combatIdMap.end()) { - return; - } - - it->second.clear(); - combatMap.clear(); -} - const std::unique_ptr<AreaCombat> &LuaEnvironment::getAreaObject(uint32_t id) const { - auto it = areaMap.find(id); + const auto it = areaMap.find(id); if (it == areaMap.end()) { return AreaCombatNull; } @@ -133,7 +109,7 @@ uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface* interface) { } void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) { - auto it = areaIdMap.find(interface); + const auto it = areaIdMap.find(interface); if (it == areaIdMap.end()) { return; } @@ -148,7 +124,7 @@ void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) { } void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) { - auto it = timerEvents.find(eventIndex); + const auto it = timerEvents.find(eventIndex); if (it == timerEvents.end()) { return; } @@ -160,7 +136,7 @@ void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) { lua_rawgeti(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); // push parameters - for (auto parameter : std::views::reverse(timerEventDesc.parameters)) { + for (const auto parameter : std::views::reverse(timerEventDesc.parameters)) { lua_rawgeti(luaState, LUA_REGISTRYINDEX, parameter); } @@ -178,7 +154,7 @@ void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) { // free resources luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - for (auto parameter : timerEventDesc.parameters) { + for (const auto parameter : timerEventDesc.parameters) { luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); } } diff --git a/src/lua/scripts/lua_environment.hpp b/src/lua/scripts/lua_environment.hpp index b467599cad4..63efd2d7033 100644 --- a/src/lua/scripts/lua_environment.hpp +++ b/src/lua/scripts/lua_environment.hpp @@ -22,7 +22,7 @@ class Cylinder; class Game; class GlobalFunctions; -class LuaEnvironment : public LuaScriptInterface { +class LuaEnvironment final : public LuaScriptInterface { public: static bool shuttingDown; @@ -35,9 +35,7 @@ class LuaEnvironment : public LuaScriptInterface { LuaEnvironment(const LuaEnvironment &) = delete; LuaEnvironment &operator=(const LuaEnvironment &) = delete; - static LuaEnvironment &getInstance() { - return inject<LuaEnvironment>(); - } + static LuaEnvironment &getInstance(); bool initState() override; bool reInitState() override; @@ -45,38 +43,6 @@ class LuaEnvironment : public LuaScriptInterface { LuaScriptInterface* getTestInterface(); - std::shared_ptr<Combat> getCombatObject(uint32_t id) const; - std::shared_ptr<Combat> createCombatObject(LuaScriptInterface* interface); - void clearCombatObjects(LuaScriptInterface* interface); - - template <typename T> - std::shared_ptr<T> createWeaponObject(LuaScriptInterface* interface) { - auto weapon = std::make_shared<T>(interface); - auto weaponId = ++lastWeaponId; - weaponMap[weaponId] = weapon; - weaponIdMap[interface].push_back(weaponId); - return weapon; - } - - template <typename T> - std::shared_ptr<T> getWeaponObject(uint32_t id) const { - auto it = weaponMap.find(id); - if (it == weaponMap.end()) { - return nullptr; - } - return it->second; - } - - void clearWeaponObjects(LuaScriptInterface* interface) { - auto it = weaponIdMap.find(interface); - if (it == weaponIdMap.end()) { - return; - } - - it->second.clear(); - weaponMap.clear(); - } - const std::unique_ptr<AreaCombat> &getAreaObject(uint32_t id) const; uint32_t createAreaObject(LuaScriptInterface* interface); void clearAreaObjects(LuaScriptInterface* interface); @@ -89,21 +55,13 @@ class LuaEnvironment : public LuaScriptInterface { private: void executeTimerEvent(uint32_t eventIndex); - phmap::flat_hash_map<uint32_t, LuaTimerEventDesc> timerEvents; + std::unordered_map<uint32_t, LuaTimerEventDesc> timerEvents; uint32_t lastEventTimerId = 1; phmap::flat_hash_map<uint32_t, std::unique_ptr<AreaCombat>> areaMap; phmap::flat_hash_map<LuaScriptInterface*, std::vector<uint32_t>> areaIdMap; uint32_t lastAreaId = 0; - phmap::flat_hash_map<uint32_t, std::shared_ptr<Combat>> combatMap; - phmap::flat_hash_map<LuaScriptInterface*, std::vector<uint32_t>> combatIdMap; - uint32_t lastCombatId = 0; - - phmap::flat_hash_map<uint32_t, std::shared_ptr<Weapon>> weaponMap; - phmap::flat_hash_map<LuaScriptInterface*, std::vector<uint32_t>> weaponIdMap; - uint32_t lastWeaponId = 0; - LuaScriptInterface* testInterface = nullptr; friend class LuaScriptInterface; diff --git a/src/lua/scripts/luascript.cpp b/src/lua/scripts/luascript.cpp index 2daab6c0532..9bb926b5676 100644 --- a/src/lua/scripts/luascript.cpp +++ b/src/lua/scripts/luascript.cpp @@ -8,6 +8,7 @@ */ #include "lua/scripts/luascript.hpp" + #include "lua/scripts/lua_environment.hpp" #include "lib/metrics/metrics.hpp" @@ -15,19 +16,18 @@ ScriptEnvironment::DBResultMap ScriptEnvironment::tempResults; uint32_t ScriptEnvironment::lastResultId = 0; std::multimap<ScriptEnvironment*, std::shared_ptr<Item>> ScriptEnvironment::tempItems; -ScriptEnvironment LuaFunctionsLoader::scriptEnv[16]; -int32_t LuaFunctionsLoader::scriptEnvIndex = -1; +ScriptEnvironment Lua::scriptEnv[16]; +int32_t Lua::scriptEnvIndex = -1; LuaScriptInterface::LuaScriptInterface(std::string initInterfaceName) : interfaceName(std::move(initInterfaceName)) { } LuaScriptInterface::~LuaScriptInterface() { - closeState(); + LuaScriptInterface::closeState(); } bool LuaScriptInterface::reInitState() { - g_luaEnvironment().clearCombatObjects(this); g_luaEnvironment().clearAreaObjects(this); closeState(); @@ -156,7 +156,7 @@ const std::string &LuaScriptInterface::getFileById(int32_t scriptId) { return loadingFile; } - auto it = cacheFiles.find(scriptId); + const auto it = cacheFiles.find(scriptId); if (it == cacheFiles.end()) { static const std::string &unk = "(Unknown scriptfile)"; return unk; @@ -164,7 +164,7 @@ const std::string &LuaScriptInterface::getFileById(int32_t scriptId) { return it->second; } -std::string LuaScriptInterface::getStackTrace(const std::string &error_desc) { +std::string LuaScriptInterface::getStackTrace(const std::string &error_desc) const { lua_getglobal(luaState, "debug"); if (!isTable(luaState, -1)) { lua_pop(luaState, 1); @@ -193,7 +193,7 @@ std::string LuaScriptInterface::getStackTrace(const std::string &error_desc) { return stackTrace; } -bool LuaScriptInterface::pushFunction(int32_t functionId) { +bool LuaScriptInterface::pushFunction(int32_t functionId) const { lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); if (!isTable(luaState, -1)) { return false; @@ -235,8 +235,9 @@ bool LuaScriptInterface::closeState() { return true; } -std::string LuaScriptInterface::getMetricsScope() { - metrics::method_latency measure(__METHOD_NAME__); +std::string LuaScriptInterface::getMetricsScope() const { +#ifdef FEATURE_METRICS + metrics::method_latency measure(__METRICS_METHOD_NAME__); int32_t scriptId; int32_t callbackId; bool timerEvent; @@ -253,19 +254,22 @@ std::string LuaScriptInterface::getMetricsScope() { if (name.empty()) { return "unknown"; } - auto pos = name.find("data"); + const auto pos = name.find("data"); if (pos != std::string::npos) { name = name.substr(pos); } } return fmt::format("{}:{}", name, timerEvent ? "timer" : "<direct>"); +#else + return {}; +#endif } -bool LuaScriptInterface::callFunction(int params) { +bool LuaScriptInterface::callFunction(int params) const { metrics::lua_latency measure(getMetricsScope()); bool result = false; - int size = lua_gettop(luaState); + const int size = lua_gettop(luaState); if (protectedCall(luaState, params, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(luaState, -1)); } else { @@ -281,9 +285,9 @@ bool LuaScriptInterface::callFunction(int params) { return result; } -void LuaScriptInterface::callVoidFunction(int params) { +void LuaScriptInterface::callVoidFunction(int params) const { metrics::lua_latency measure(getMetricsScope()); - int size = lua_gettop(luaState); + const int size = lua_gettop(luaState); if (protectedCall(luaState, params, 0) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(luaState)); } diff --git a/src/lua/scripts/luascript.hpp b/src/lua/scripts/luascript.hpp index a376babedde..c4d916a593c 100644 --- a/src/lua/scripts/luascript.hpp +++ b/src/lua/scripts/luascript.hpp @@ -12,7 +12,7 @@ #include "lua/functions/lua_functions_loader.hpp" #include "lua/scripts/script_environment.hpp" -class LuaScriptInterface : public LuaFunctionsLoader { +class LuaScriptInterface : public Lua { public: explicit LuaScriptInterface(std::string interfaceName); virtual ~LuaScriptInterface(); @@ -57,12 +57,12 @@ class LuaScriptInterface : public LuaFunctionsLoader { return luaState; } - bool pushFunction(int32_t functionId); + bool pushFunction(int32_t functionId) const; - bool callFunction(int params); - void callVoidFunction(int params); + bool callFunction(int params) const; + void callVoidFunction(int params) const; - std::string getStackTrace(const std::string &error_desc); + std::string getStackTrace(const std::string &error_desc) const; protected: virtual bool closeState(); @@ -72,7 +72,7 @@ class LuaScriptInterface : public LuaFunctionsLoader { std::map<int32_t, std::string> cacheFiles; private: - std::string getMetricsScope(); + std::string getMetricsScope() const; std::string lastLuaError; std::string interfaceName; diff --git a/src/lua/scripts/script_environment.cpp b/src/lua/scripts/script_environment.cpp index e1c5e3a9c85..80eea882fa0 100644 --- a/src/lua/scripts/script_environment.cpp +++ b/src/lua/scripts/script_environment.cpp @@ -7,9 +7,11 @@ * Website: https://docs.opentibiabr.com/ */ +#include "lua/scripts/script_environment.hpp" + +#include "creatures/creature.hpp" #include "game/game.hpp" #include "lua/scripts/luascript.hpp" -#include "lua/scripts/script_environment.hpp" ScriptEnvironment::ScriptEnvironment() { resetEnv(); @@ -27,10 +29,10 @@ void ScriptEnvironment::resetEnv() { localMap.clear(); tempResults.clear(); - auto pair = tempItems.equal_range(this); - auto it = pair.first; - while (it != pair.second) { - std::shared_ptr<Item> item = it->second; + const auto [fst, snd] = tempItems.equal_range(this); + auto it = fst; + while (it != snd) { + const auto item = it->second; it = tempItems.erase(it); } } @@ -39,7 +41,7 @@ bool ScriptEnvironment::setCallbackId(int32_t newCallbackId, LuaScriptInterface* if (this->callbackId != 0) { // nested callbacks are not allowed if (interface) { - interface->reportErrorFunc("Nested callbacks!"); + LuaScriptInterface::reportErrorFunc("Nested callbacks!"); } return false; } @@ -56,24 +58,24 @@ void ScriptEnvironment::getEventInfo(int32_t &retScriptId, LuaScriptInterface*&r retTimerEvent = this->timerEvent; } -uint32_t ScriptEnvironment::addThing(std::shared_ptr<Thing> thing) { +uint32_t ScriptEnvironment::addThing(const std::shared_ptr<Thing> &thing) { if (!thing || thing->isRemoved()) { return 0; } - std::shared_ptr<Creature> creature = thing->getCreature(); + const auto &creature = thing->getCreature(); if (creature) { return creature->getID(); } - std::shared_ptr<Item> item = thing->getItem(); + const auto &item = thing->getItem(); if (item && item->hasAttribute(ItemAttribute_t::UNIQUEID)) { return item->getAttribute<uint32_t>(ItemAttribute_t::UNIQUEID); } - for (const auto &it : localMap) { - if (it.second == item) { - return it.first; + for (const auto &[itemId, itemPtr] : localMap) { + if (itemPtr == item) { + return itemId; } } @@ -82,8 +84,8 @@ uint32_t ScriptEnvironment::addThing(std::shared_ptr<Thing> thing) { } void ScriptEnvironment::insertItem(uint32_t uid, std::shared_ptr<Item> item) { - auto result = localMap.emplace(uid, item); - if (!result.second) { + const auto [fst, snd] = localMap.emplace(uid, item); + if (!snd) { g_logger().error("Thing uid already taken: {}", uid); } } @@ -94,16 +96,16 @@ std::shared_ptr<Thing> ScriptEnvironment::getThingByUID(uint32_t uid) { } if (uid <= std::numeric_limits<uint16_t>::max()) { - std::shared_ptr<Item> item = g_game().getUniqueItem(static_cast<uint16_t>(uid)); + const auto &item = g_game().getUniqueItem(static_cast<uint16_t>(uid)); if (item && !item->isRemoved()) { return item; } return nullptr; } - auto it = localMap.find(uid); + const auto it = localMap.find(uid); if (it != localMap.end()) { - std::shared_ptr<Item> item = it->second; + const auto &item = it->second; if (!item->isRemoved()) { return item; } @@ -112,7 +114,7 @@ std::shared_ptr<Thing> ScriptEnvironment::getThingByUID(uint32_t uid) { } std::shared_ptr<Item> ScriptEnvironment::getItemByUID(uint32_t uid) { - std::shared_ptr<Thing> thing = getThingByUID(uid); + const auto &thing = getThingByUID(uid); if (!thing) { return nullptr; } @@ -120,7 +122,7 @@ std::shared_ptr<Item> ScriptEnvironment::getItemByUID(uint32_t uid) { } std::shared_ptr<Container> ScriptEnvironment::getContainerByUID(uint32_t uid) { - std::shared_ptr<Item> item = getItemByUID(uid); + const auto &item = getItemByUID(uid); if (!item) { return nullptr; } @@ -133,17 +135,17 @@ void ScriptEnvironment::removeItemByUID(uint32_t uid) { return; } - auto it = localMap.find(uid); + const auto it = localMap.find(uid); if (it != localMap.end()) { localMap.erase(it); } } -void ScriptEnvironment::addTempItem(std::shared_ptr<Item> item) { +void ScriptEnvironment::addTempItem(const std::shared_ptr<Item> &item) { tempItems.emplace(this, item); } -void ScriptEnvironment::removeTempItem(std::shared_ptr<Item> item) { +void ScriptEnvironment::removeTempItem(const std::shared_ptr<Item> &item) { for (auto it = tempItems.begin(), end = tempItems.end(); it != end; ++it) { if (it->second == item) { tempItems.erase(it); @@ -153,12 +155,12 @@ void ScriptEnvironment::removeTempItem(std::shared_ptr<Item> item) { } uint32_t ScriptEnvironment::addResult(DBResult_ptr res) { - tempResults[++lastResultId] = res; + tempResults[++lastResultId] = std::move(res); return lastResultId; } bool ScriptEnvironment::removeResult(uint32_t id) { - auto it = tempResults.find(id); + const auto it = tempResults.find(id); if (it == tempResults.end()) { return false; } @@ -168,7 +170,7 @@ bool ScriptEnvironment::removeResult(uint32_t id) { } DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) { - auto it = tempResults.find(id); + const auto it = tempResults.find(id); if (it == tempResults.end()) { return nullptr; } diff --git a/src/lua/scripts/script_environment.hpp b/src/lua/scripts/script_environment.hpp index fe89d3f1e5d..54faf81b7c3 100644 --- a/src/lua/scripts/script_environment.hpp +++ b/src/lua/scripts/script_environment.hpp @@ -22,10 +22,10 @@ class LuaScriptInterface; class Cylinder; class Game; -class ScriptEnvironment { +class ScriptEnvironment final { public: ScriptEnvironment(); - virtual ~ScriptEnvironment(); + ~ScriptEnvironment(); // non-copyable ScriptEnvironment(const ScriptEnvironment &) = delete; @@ -42,7 +42,7 @@ class ScriptEnvironment { int32_t getScriptId() const { return scriptId; } - LuaScriptInterface* getScriptInterface() { + LuaScriptInterface* getScriptInterface() const { return interface; } @@ -52,9 +52,9 @@ class ScriptEnvironment { void getEventInfo(int32_t &scriptId, LuaScriptInterface*&scriptInterface, int32_t &callbackId, bool &timerEvent) const; - void addTempItem(std::shared_ptr<Item> item); - static void removeTempItem(std::shared_ptr<Item> item); - uint32_t addThing(std::shared_ptr<Thing> thing); + void addTempItem(const std::shared_ptr<Item> &item); + static void removeTempItem(const std::shared_ptr<Item> &item); + uint32_t addThing(const std::shared_ptr<Thing> &thing); void insertItem(uint32_t uid, std::shared_ptr<Item> item); static DBResult_ptr getResultByID(uint32_t id); @@ -62,7 +62,7 @@ class ScriptEnvironment { static bool removeResult(uint32_t id); void setNpc(std::shared_ptr<Npc> npc) { - curNpc = npc; + curNpc = std::move(npc); } std::shared_ptr<Npc> getNpc() const { return curNpc; @@ -77,7 +77,7 @@ class ScriptEnvironment { using StorageMap = std::map<uint32_t, int32_t>; using DBResultMap = std::map<uint32_t, DBResult_ptr>; - LuaScriptInterface* interface; + LuaScriptInterface* interface {}; // for npc scripts std::shared_ptr<Npc> curNpc = nullptr; @@ -90,9 +90,9 @@ class ScriptEnvironment { uint32_t lastUID = std::numeric_limits<uint16_t>::max(); // script file id - int32_t scriptId; - int32_t callbackId; - bool timerEvent; + int32_t scriptId {}; + int32_t callbackId {}; + bool timerEvent {}; // result map static uint32_t lastResultId; diff --git a/src/lua/scripts/scripts.cpp b/src/lua/scripts/scripts.cpp index 6e2add673d8..f4a141253c4 100644 --- a/src/lua/scripts/scripts.cpp +++ b/src/lua/scripts/scripts.cpp @@ -7,19 +7,29 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/players/imbuements/imbuements.hpp" -#include "lua/global/globalevent.hpp" -#include "items/weapons/weapons.hpp" -#include "lua/creature/movement.hpp" #include "lua/scripts/scripts.hpp" + +#include "lib/di/container.hpp" +#include "config/configmanager.hpp" #include "creatures/combat/spells.hpp" +#include "creatures/monsters/monsters.hpp" +#include "items/weapons/weapons.hpp" #include "lua/callbacks/events_callbacks.hpp" +#include "lua/creature/creatureevent.hpp" +#include "lua/creature/movement.hpp" +#include "lua/creature/talkaction.hpp" +#include "lua/global/globalevent.hpp" Scripts::Scripts() : scriptInterface("Scripts Interface") { scriptInterface.initState(); } +Scripts &Scripts::getInstance() { + static Scripts instance; + return instance; +} + void Scripts::clearAllScripts() const { g_actions().clear(); g_creatureEvents().clear(); @@ -40,7 +50,7 @@ bool Scripts::loadEventSchedulerScripts(const std::string &fileName) { return false; } - std::filesystem::recursive_directory_iterator endit; + const std::filesystem::recursive_directory_iterator endit; for (std::filesystem::recursive_directory_iterator it(dir); it != endit; ++it) { if (std::filesystem::is_regular_file(*it) && it->path().extension() == ".lua") { if (it->path().filename().string() == fileName) { @@ -57,28 +67,33 @@ bool Scripts::loadEventSchedulerScripts(const std::string &fileName) { return false; } -bool Scripts::loadScripts(std::string loadPath, bool isLib, bool reload) { - const auto dir = std::filesystem::current_path() / loadPath; +bool Scripts::loadScripts(std::string_view folderName, bool isLib, bool reload) { + const auto dir = std::filesystem::current_path() / folderName; + // Checks if the folder exists and is really a folder if (!std::filesystem::exists(dir) || !std::filesystem::is_directory(dir)) { - g_logger().error("Can not load folder {}", loadPath); + g_logger().error("Can not load folder {}", folderName); return false; } // Declare a string variable to store the last directory std::string lastDirectory; + // Recursive iterate through all entries in the directory for (const auto &entry : std::filesystem::recursive_directory_iterator(dir)) { // Get the filename of the entry as a string - const auto realPath = entry.path(); + const auto &realPath = entry.path(); std::string fileFolder = realPath.parent_path().filename().string(); // Script folder, example: "actions" std::string scriptFolder = realPath.parent_path().string(); + // Create a string_view for the fileFolder and scriptFolder strings - std::string_view fileFolderView(fileFolder); - std::string_view scriptFolderView(scriptFolder); + const std::string_view fileFolderView(fileFolder); + const std::string_view scriptFolderView(scriptFolder); + // Filename, example: "demon.lua" std::string file(realPath.filename().string()); + if (!std::filesystem::is_regular_file(entry) || realPath.extension() != ".lua") { // Skip this entry if it is not a regular file or does not have a .lua extension continue; diff --git a/src/lua/scripts/scripts.hpp b/src/lua/scripts/scripts.hpp index 7cefaaaf8bd..2efedb04232 100644 --- a/src/lua/scripts/scripts.hpp +++ b/src/lua/scripts/scripts.hpp @@ -9,118 +9,27 @@ #pragma once -#include "lib/di/container.hpp" #include "lua/scripts/luascript.hpp" class Scripts { public: - Scripts(); - // non-copyable Scripts(const Scripts &) = delete; Scripts &operator=(const Scripts &) = delete; - static Scripts &getInstance() { - return inject<Scripts>(); - } + static Scripts &getInstance(); void clearAllScripts() const; bool loadEventSchedulerScripts(const std::string &fileName); - bool loadScripts(std::string folderName, bool isLib, bool reload); + bool loadScripts(std::string_view folderName, bool isLib, bool reload); LuaScriptInterface &getScriptInterface() { return scriptInterface; } - /** - * @brief Get the Script Id object - * - * @return int32_t - */ - int32_t getScriptId() const { - return scriptId; - } private: - int32_t scriptId = 0; LuaScriptInterface scriptInterface; + Scripts(); }; constexpr auto g_scripts = Scripts::getInstance; - -class Script { -public: - /** - * @brief Explicit construtor - * explicit, that is, it cannot be used for implicit conversions and - * copy-initialization. - * - * @param interface Lua Script Interface - */ - explicit Script(LuaScriptInterface* interface) : - scriptInterface(interface) { } - virtual ~Script() = default; - - /** - * @brief Check if script is loaded - * - * @return true - * @return false - */ - bool isLoadedCallback() const { - return loadedCallback; - } - void setLoadedCallback(bool loaded) { - loadedCallback = loaded; - } - - // Load revscriptsys callback - bool loadCallback() { - if (!scriptInterface) { - g_logger().error("[Script::loadCallback] scriptInterface is nullptr, scriptid = {}", scriptId); - return false; - } - - if (scriptId != 0) { - g_logger().error("[Script::loadCallback] scriptid is not zero, scriptid = {}, scriptName {}", scriptId, scriptInterface->getLoadingScriptName()); - return false; - } - - int32_t id = scriptInterface->getEvent(); - if (id == -1) { - g_logger().error("[Script::loadCallback] Event {} not found for script with name {}", getScriptTypeName(), scriptInterface->getLoadingScriptName()); - return false; - } - - setLoadedCallback(true); - scriptId = id; - return true; - } - - // NOTE: Pure virtual method ( = 0) that must be implemented in derived classes - // Script type (Action, CreatureEvent, GlobalEvent, MoveEvent, Spell, Weapon) - virtual std::string getScriptTypeName() const = 0; - - // Method to access the scriptInterface in derived classes - virtual LuaScriptInterface* getScriptInterface() const { - return scriptInterface; - } - - virtual void setScriptInterface(LuaScriptInterface* newInterface) { - scriptInterface = newInterface; - } - - // Method to access the scriptId in derived classes - virtual int32_t getScriptId() const { - return scriptId; - } - virtual void setScriptId(int32_t newScriptId) { - scriptId = newScriptId; - } - -private: - // If script is loaded callback - bool loadedCallback = false; - - int32_t scriptId = 0; - LuaScriptInterface* scriptInterface = nullptr; -}; diff --git a/src/map/house/house.cpp b/src/map/house/house.cpp index 9995862c679..6d93561172b 100644 --- a/src/map/house/house.cpp +++ b/src/map/house/house.cpp @@ -7,18 +7,23 @@ * Website: https://docs.opentibiabr.com/ */ -#include "utils/pugicast.hpp" #include "map/house/house.hpp" -#include "io/iologindata.hpp" + +#include "config/configmanager.hpp" #include "game/game.hpp" -#include "items/bed.hpp" #include "game/scheduling/save_manager.hpp" +#include "io/ioguild.hpp" +#include "io/iologindata.hpp" +#include "items/bed.hpp" +#include "items/containers/inbox/inbox.hpp" #include "lib/metrics/metrics.hpp" +#include "utils/pugicast.hpp" +#include "creatures/players/player.hpp" House::House(uint32_t houseId) : id(houseId) { } -void House::addTile(std::shared_ptr<HouseTile> tile) { +void House::addTile(const std::shared_ptr<HouseTile> &tile) { tile->setFlag(TILESTATE_PROTECTIONZONE); houseTiles.push_back(tile); updateDoorDescription(); @@ -63,7 +68,7 @@ void House::clearHouseInfo(bool preventOwnerDeletion) { } } -bool House::tryTransferOwnership(std::shared_ptr<Player> player, bool serverStartup) { +bool House::tryTransferOwnership(const std::shared_ptr<Player> &player, bool serverStartup) { bool transferSuccess = false; if (player) { transferSuccess = transferToDepot(player); @@ -74,7 +79,7 @@ bool House::tryTransferOwnership(std::shared_ptr<Player> player, bool serverStar for (const auto &tile : houseTiles) { if (const CreatureVector* creatures = tile->getCreatures()) { for (int32_t i = creatures->size(); --i >= 0;) { - const auto creature = (*creatures)[i]; + const auto &creature = (*creatures)[i]; kickPlayer(nullptr, creature->getPlayer()); } } @@ -85,7 +90,7 @@ bool House::tryTransferOwnership(std::shared_ptr<Player> player, bool serverStar return transferSuccess; } -void House::setOwner(uint32_t guid, bool updateDatabase /* = true*/, std::shared_ptr<Player> player /* = nullptr*/) { +void House::setOwner(uint32_t guid, bool updateDatabase /* = true*/, const std::shared_ptr<Player> &player /* = nullptr*/) { if (updateDatabase && owner != guid) { Database &db = Database::getInstance(); @@ -101,7 +106,7 @@ void House::setOwner(uint32_t guid, bool updateDatabase /* = true*/, std::shared isLoaded = true; if (owner != 0) { - tryTransferOwnership(std::move(player), false); + tryTransferOwnership(player, false); } else { std::string strRentPeriod = asLowerCaseString(g_configManager().getString(HOUSE_RENT_PERIOD)); time_t currentTime = time(nullptr); @@ -126,12 +131,12 @@ void House::setOwner(uint32_t guid, bool updateDatabase /* = true*/, std::shared Database &db = Database::getInstance(); std::ostringstream query; query << "SELECT `name`, `account_id` FROM `players` WHERE `id` = " << guid; - DBResult_ptr result = db.storeQuery(query.str()); + const DBResult_ptr result = db.storeQuery(query.str()); if (!result) { return; } - std::string name = result->getString("name"); + const std::string name = result->getString("name"); if (!name.empty()) { owner = guid; ownerName = name; @@ -167,7 +172,7 @@ void House::updateDoorDescription() const { } } -AccessHouseLevel_t House::getHouseAccessLevel(std::shared_ptr<Player> player) const { +AccessHouseLevel_t House::getHouseAccessLevel(const std::shared_ptr<Player> &player) const { if (!player) { return HOUSE_OWNER; } @@ -197,12 +202,12 @@ AccessHouseLevel_t House::getHouseAccessLevel(std::shared_ptr<Player> player) co return HOUSE_NOT_INVITED; } -bool House::kickPlayer(std::shared_ptr<Player> player, std::shared_ptr<Player> target) { +bool House::kickPlayer(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target) { if (!target) { return false; } - std::shared_ptr<HouseTile> houseTile = std::dynamic_pointer_cast<HouseTile>(target->getTile()); + const auto &houseTile = std::dynamic_pointer_cast<HouseTile>(target->getTile()); if (!houseTile || houseTile->getHouse() != static_self_cast<House>()) { return false; } @@ -211,7 +216,7 @@ bool House::kickPlayer(std::shared_ptr<Player> player, std::shared_ptr<Player> t return false; } - Position oldPosition = target->getPosition(); + const Position oldPosition = target->getPosition(); if (g_game().internalTeleport(target, getEntryPosition()) == RETURNVALUE_NOERROR) { g_game().addMagicEffect(oldPosition, CONST_ME_POFF); g_game().addMagicEffect(getEntryPosition(), CONST_ME_TELEPORT); @@ -225,7 +230,7 @@ void House::setAccessList(uint32_t listId, const std::string &textlist) { } else if (listId == SUBOWNER_LIST) { subOwnerList.parseList(textlist); } else { - std::shared_ptr<Door> door = getDoorByNumber(listId); + const auto &door = getDoorByNumber(listId); if (door) { door->setAccessList(textlist); } @@ -236,9 +241,9 @@ void House::setAccessList(uint32_t listId, const std::string &textlist) { // kick uninvited players for (const std::shared_ptr<HouseTile> &tile : houseTiles) { - if (CreatureVector* creatures = tile->getCreatures()) { + if (const CreatureVector* creatures = tile->getCreatures()) { for (int32_t i = creatures->size(); --i >= 0;) { - std::shared_ptr<Player> player = (*creatures)[i]->getPlayer(); + const auto &player = (*creatures)[i]->getPlayer(); if (player && !isInvited(player)) { kickPlayer(nullptr, player); } @@ -252,11 +257,11 @@ bool House::transferToDepot() const { return false; } - std::shared_ptr<Player> player = g_game().getPlayerByGUID(owner); + const auto &player = g_game().getPlayerByGUID(owner); if (player) { transferToDepot(player); } else { - std::shared_ptr<Player> tmpPlayer = std::make_shared<Player>(nullptr); + const auto tmpPlayer = std::make_shared<Player>(nullptr); if (!IOLoginData::loadPlayerById(tmpPlayer, owner)) { return false; } @@ -266,11 +271,11 @@ bool House::transferToDepot() const { return true; } -bool House::transferToDepot(std::shared_ptr<Player> player) const { +bool House::transferToDepot(const std::shared_ptr<Player> &player) const { if (townId == 0 || !player) { return false; } - for (const std::shared_ptr<HouseTile> &tile : houseTiles) { + for (const auto &tile : houseTiles) { if (!transferToDepot(player, tile)) { return false; } @@ -278,7 +283,7 @@ bool House::transferToDepot(std::shared_ptr<Player> player) const { return true; } -bool House::transferToDepot(std::shared_ptr<Player> player, std::shared_ptr<HouseTile> tile) const { +bool House::transferToDepot(const std::shared_ptr<Player> &player, const std::shared_ptr<HouseTile> &tile) const { if (townId == 0 || !player) { return false; } @@ -289,7 +294,7 @@ bool House::transferToDepot(std::shared_ptr<Player> player, std::shared_ptr<Hous ItemList moveItemList; if (const TileItemVector* items = tile->getItemList()) { - for (const std::shared_ptr<Item> &item : *items) { + for (const auto &item : *items) { if (item->isWrapable()) { handleWrapableItem(moveItemList, item, player, tile); } else if (item->isPickupable()) { @@ -302,7 +307,7 @@ bool House::transferToDepot(std::shared_ptr<Player> player, std::shared_ptr<Hous std::unordered_set<std::shared_ptr<Player>> playersToSave = { player }; - for (const std::shared_ptr<Item> &item : moveItemList) { + for (const auto &item : moveItemList) { g_logger().debug("[{}] moving item '{}' to depot", __FUNCTION__, item->getName()); auto targetPlayer = player; if (item->hasOwner() && !item->isOwner(targetPlayer)) { @@ -323,9 +328,9 @@ bool House::transferToDepot(std::shared_ptr<Player> player, std::shared_ptr<Hous bool House::hasItemOnTile() const { bool foundItem = false; - for (const std::shared_ptr<HouseTile> &tile : houseTiles) { + for (const auto &tile : houseTiles) { if (const auto &items = tile->getItemList()) { - for (const std::shared_ptr<Item> &item : *items) { + for (const auto &item : *items) { if (!item) { continue; } @@ -360,13 +365,13 @@ void House::setNewOwnership() { hasNewOwnerOnStartup = true; } -void House::handleWrapableItem(ItemList &moveItemList, std::shared_ptr<Item> item, std::shared_ptr<Player> player, std::shared_ptr<HouseTile> houseTile) const { +void House::handleWrapableItem(ItemList &moveItemList, const std::shared_ptr<Item> &item, const std::shared_ptr<Player> &player, const std::shared_ptr<HouseTile> &houseTile) const { if (item->isWrapContainer()) { g_logger().debug("[{}] found wrapable item '{}'", __FUNCTION__, item->getName()); handleContainer(moveItemList, item); } - std::shared_ptr<Item> newItem = g_game().wrapItem(item, houseTile->getHouse()); + const auto &newItem = g_game().wrapItem(item, houseTile->getHouse()); if (newItem->isRemoved() && !newItem->getParent()) { g_logger().warn("[{}] item removed during wrapping - check ground type - player name: {} item id: {} position: {}", __FUNCTION__, player->getName(), item->getID(), houseTile->getPosition().toString()); return; @@ -375,9 +380,9 @@ void House::handleWrapableItem(ItemList &moveItemList, std::shared_ptr<Item> ite moveItemList.push_back(newItem); } -void House::handleContainer(ItemList &moveItemList, std::shared_ptr<Item> item) const { - if (const auto container = item->getContainer()) { - for (const std::shared_ptr<Item> &containerItem : container->getItemList()) { +void House::handleContainer(ItemList &moveItemList, const std::shared_ptr<Item> &item) const { + if (const auto &container = item->getContainer()) { + for (const auto &containerItem : container->getItemList()) { moveItemList.push_back(containerItem); } } @@ -392,7 +397,7 @@ bool House::getAccessList(uint32_t listId, std::string &list) const { return true; } - std::shared_ptr<Door> door = getDoorByNumber(listId); + const auto &door = getDoorByNumber(listId); if (!door) { return false; } @@ -400,25 +405,25 @@ bool House::getAccessList(uint32_t listId, std::string &list) const { return door->getAccessList(list); } -void House::addDoor(std::shared_ptr<Door> door) { +void House::addDoor(const std::shared_ptr<Door> &door) { doorList.push_back(door); door->setHouse(static_self_cast<House>()); updateDoorDescription(); } -void House::removeDoor(std::shared_ptr<Door> door) { - auto it = std::find(doorList.begin(), doorList.end(), door); +void House::removeDoor(const std::shared_ptr<Door> &door) { + auto it = std::ranges::find(doorList, door); if (it != doorList.end()) { doorList.erase(it); } } -void House::addBed(std::shared_ptr<BedItem> bed) { +void House::addBed(const std::shared_ptr<BedItem> &bed) { bedsList.push_back(bed); bed->setHouse(static_self_cast<House>()); } -void House::removeBed(std::shared_ptr<BedItem> bed) { +void House::removeBed(const std::shared_ptr<BedItem> &bed) { bed->setHouse(nullptr); bedsList.remove(bed); } @@ -432,8 +437,8 @@ std::shared_ptr<Door> House::getDoorByNumber(uint32_t doorId) const { return nullptr; } -std::shared_ptr<Door> House::getDoorByPosition(const Position &pos) { - for (std::shared_ptr<Door> door : doorList) { +std::shared_ptr<Door> House::getDoorByPosition(const Position &pos) const { + for (const auto &door : doorList) { if (door->getPosition() == pos) { return door; } @@ -467,15 +472,15 @@ std::shared_ptr<HouseTransferItem> House::getTransferItem() { void House::resetTransferItem() { if (transferItem) { - std::shared_ptr<Item> tmpItem = transferItem; + auto tmpItem = transferItem; transferItem = nullptr; transfer_container->resetParent(); transfer_container->removeThing(tmpItem, tmpItem->getItemCount()); } } -std::shared_ptr<HouseTransferItem> HouseTransferItem::createHouseTransferItem(std::shared_ptr<House> house) { - std::shared_ptr<HouseTransferItem> transferItem = std::make_shared<HouseTransferItem>(house); +std::shared_ptr<HouseTransferItem> HouseTransferItem::createHouseTransferItem(const std::shared_ptr<House> &house) { + auto transferItem = std::make_shared<HouseTransferItem>(house); transferItem->setID(ITEM_DOCUMENT_RO); transferItem->setSubType(1); std::ostringstream ss; @@ -484,17 +489,17 @@ std::shared_ptr<HouseTransferItem> HouseTransferItem::createHouseTransferItem(st return transferItem; } -void HouseTransferItem::onTradeEvent(TradeEvents_t event, std::shared_ptr<Player> owner) { +void HouseTransferItem::onTradeEvent(TradeEvents_t event, const std::shared_ptr<Player> &owner) { if (event == ON_TRADE_TRANSFER) { if (house) { auto isTransferOnRestart = g_configManager().getBoolean(TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART); auto ownershipTransferMessage = " The ownership will be transferred upon server restart."; - auto boughtMessage = fmt::format("You have successfully bought the house.{}", isTransferOnRestart ? ownershipTransferMessage : ""); - auto soldMessage = fmt::format("You have successfully sold your house.{}", isTransferOnRestart ? ownershipTransferMessage : ""); + const auto boughtMessage = fmt::format("You have successfully bought the house.{}", isTransferOnRestart ? ownershipTransferMessage : ""); + const auto soldMessage = fmt::format("You have successfully sold your house.{}", isTransferOnRestart ? ownershipTransferMessage : ""); owner->sendTextMessage(MESSAGE_EVENT_ADVANCE, boughtMessage); - auto oldOwner = g_game().getPlayerByGUID(house->getOwner()); + const auto oldOwner = g_game().getPlayerByGUID(house->getOwner()); if (oldOwner) { oldOwner->sendTextMessage(MESSAGE_EVENT_ADVANCE, soldMessage); } @@ -509,7 +514,7 @@ void HouseTransferItem::onTradeEvent(TradeEvents_t event, std::shared_ptr<Player } } -bool House::executeTransfer(std::shared_ptr<HouseTransferItem> item, std::shared_ptr<Player> newOwner) { +bool House::executeTransfer(const std::shared_ptr<HouseTransferItem> &item, const std::shared_ptr<Player> &newOwner) { if (transferItem != item) { return false; } @@ -529,7 +534,7 @@ bool House::executeTransfer(std::shared_ptr<HouseTransferItem> item, std::shared } void AccessList::parseList(const std::string &list) { - std::regex regexValidChars("[^a-zA-Z' \n*!@#]+"); + const std::regex regexValidChars("[^a-zA-Z' \n*!@#]+"); std::string validList = std::regex_replace(list, regexValidChars, ""); // Remove empty lines @@ -564,7 +569,7 @@ void AccessList::parseList(const std::string &list) { toLowerCaseString(m_line); - std::string::size_type at_pos = m_line.find('@'); + const std::string::size_type at_pos = m_line.find('@'); if (at_pos != std::string::npos) { if (at_pos == 0) { addGuild(m_line.substr(1)); @@ -583,11 +588,11 @@ void AccessList::parseList(const std::string &list) { } void AccessList::addPlayer(const std::string &name) { - std::shared_ptr<Player> player = g_game().getPlayerByName(name); + const auto &player = g_game().getPlayerByName(name); if (player) { playerList.insert(player->getGUID()); } else { - uint32_t guid = IOLoginData::getGuidByName(name); + const uint32_t guid = IOLoginData::getGuidByName(name); if (guid != 0) { playerList.insert(guid); } @@ -596,12 +601,12 @@ void AccessList::addPlayer(const std::string &name) { namespace { std::shared_ptr<Guild> getGuildByName(const std::string &name) { - uint32_t guildId = IOGuild::getGuildIdByName(name); + const uint32_t guildId = IOGuild::getGuildIdByName(name); if (guildId == 0) { return nullptr; } - auto guild = g_game().getGuild(guildId); + const auto &guild = g_game().getGuild(guildId); if (guild) { return guild; } @@ -611,7 +616,7 @@ namespace { } void AccessList::addGuild(const std::string &name) { - const auto guild = getGuildByName(name); + const auto &guild = getGuildByName(name); if (guild) { for (const auto &rank : guild->getRanks()) { guildRankList.insert(rank->id); @@ -620,16 +625,16 @@ void AccessList::addGuild(const std::string &name) { } void AccessList::addGuildRank(const std::string &name, const std::string &guildName) { - const auto guild = getGuildByName(guildName); + const auto &guild = getGuildByName(guildName); if (guild) { - const GuildRank_ptr rank = guild->getRankByName(name); + const GuildRank_ptr &rank = guild->getRankByName(name); if (rank) { guildRankList.insert(rank->id); } } } -bool AccessList::isInList(std::shared_ptr<Player> player) const { +bool AccessList::isInList(const std::shared_ptr<Player> &player) const { if (allowEveryone) { return true; } @@ -674,7 +679,7 @@ void Door::setHouse(std::shared_ptr<House> newHouse) { } } -bool Door::canUse(std::shared_ptr<Player> player) const { +bool Door::canUse(const std::shared_ptr<Player> &player) const { if (!house) { return true; } @@ -711,7 +716,7 @@ void Door::onRemoved() { } } -std::shared_ptr<House> Houses::getHouseByPlayerId(uint32_t playerId) { +std::shared_ptr<House> Houses::getHouseByPlayerId(uint32_t playerId) const { for (const auto &it : houseMap) { if (it.second->getOwner() == playerId) { return it.second; @@ -722,21 +727,21 @@ std::shared_ptr<House> Houses::getHouseByPlayerId(uint32_t playerId) { bool Houses::loadHousesXML(const std::string &filename) { pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); + const pugi::xml_parse_result result = doc.load_file(filename.c_str()); if (!result) { printXMLError(__FUNCTION__, filename, result); return false; } - for (auto houseNode : doc.child("houses").children()) { + for (const auto &houseNode : doc.child("houses").children()) { pugi::xml_attribute houseIdAttribute = houseNode.attribute("houseid"); if (!houseIdAttribute) { return false; } - int32_t houseId = pugi::cast<int32_t>(houseIdAttribute.value()); + auto houseId = pugi::cast<int32_t>(houseIdAttribute.value()); - std::shared_ptr<House> house = getHouse(houseId); + const auto &house = getHouse(houseId); if (!house) { g_logger().error("[Houses::loadHousesXML] - Unknown house, id: {}", houseId); return false; @@ -744,7 +749,7 @@ bool Houses::loadHousesXML(const std::string &filename) { house->setName(houseNode.attribute("name").as_string()); - Position entryPos( + const Position entryPos( pugi::cast<uint16_t>(houseNode.attribute("entryx").value()), pugi::cast<uint16_t>(houseNode.attribute("entryy").value()), pugi::cast<uint16_t>(houseNode.attribute("entryz").value()) @@ -776,9 +781,9 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { return; } - time_t currentTime = time(nullptr); + const time_t currentTime = time(nullptr); for (const auto &it : houseMap) { - std::shared_ptr<House> house = it.second; + const auto &house = it.second; if (house->getOwner() == 0) { continue; } @@ -789,7 +794,7 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { continue; } - auto player = g_game().getPlayerByGUID(ownerId, true); + const auto &player = g_game().getPlayerByGUID(ownerId, true); if (!player) { // Player doesn't exist, reset house owner house->tryTransferOwnership(nullptr, true); @@ -842,9 +847,9 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { house->setPaidUntil(paidUntil); } else { if (house->getPayRentWarnings() < 7) { - int32_t daysLeft = 7 - house->getPayRentWarnings(); + const int32_t daysLeft = 7 - house->getPayRentWarnings(); - std::shared_ptr<Item> letter = Item::CreateItem(ITEM_LETTER_STAMPED); + const std::shared_ptr<Item> &letter = Item::CreateItem(ITEM_LETTER_STAMPED); std::string period; switch (rentPeriod) { @@ -871,7 +876,8 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const { std::ostringstream ss; ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house."; letter->setAttribute(ItemAttribute_t::TEXT, ss.str()); - g_game().internalAddItem(player->getInbox(), letter, INDEX_WHEREEVER, FLAG_NOLIMIT); + const auto &playerInbox = player->getInbox(); + g_game().internalAddItem(playerInbox, letter, INDEX_WHEREEVER, FLAG_NOLIMIT); house->setPayRentWarnings(house->getPayRentWarnings() + 1); } else { house->setOwner(0, true, player); diff --git a/src/map/house/house.hpp b/src/map/house/house.hpp index aa4b746cc0a..a3dc765988f 100644 --- a/src/map/house/house.hpp +++ b/src/map/house/house.hpp @@ -25,7 +25,7 @@ class AccessList { void addGuild(const std::string &name); void addGuildRank(const std::string &name, const std::string &rankName); - bool isInList(std::shared_ptr<Player> player) const; + bool isInList(const std::shared_ptr<Player> &player) const; void getList(std::string &list) const; @@ -63,7 +63,7 @@ class Door final : public Item { return getAttribute<uint32_t>(ItemAttribute_t::DOORID); } - bool canUse(std::shared_ptr<Player> player) const; + bool canUse(const std::shared_ptr<Player> &player) const; void setAccessList(const std::string &textlist); bool getAccessList(std::string &list) const; @@ -83,12 +83,12 @@ using HouseBedItemList = std::list<std::shared_ptr<BedItem>>; class HouseTransferItem final : public Item { public: - static std::shared_ptr<HouseTransferItem> createHouseTransferItem(std::shared_ptr<House> house); + static std::shared_ptr<HouseTransferItem> createHouseTransferItem(const std::shared_ptr<House> &house); explicit HouseTransferItem(std::shared_ptr<House> newHouse) : - Item(0), house(newHouse) { } + Item(0), house(std::move(newHouse)) { } - void onTradeEvent(TradeEvents_t event, std::shared_ptr<Player> owner) override; + void onTradeEvent(TradeEvents_t event, const std::shared_ptr<Player> &owner) override; bool canTransform() const override { return false; } @@ -97,11 +97,11 @@ class HouseTransferItem final : public Item { std::shared_ptr<House> house; }; -class House : public SharedObject { +class House final : public SharedObject { public: explicit House(uint32_t houseId); - void addTile(std::shared_ptr<HouseTile> tile); + void addTile(const std::shared_ptr<HouseTile> &tile); void updateDoorDescription() const; bool canEditAccessList(uint32_t listId, const std::shared_ptr<Player> &player) const; @@ -115,8 +115,8 @@ class House : public SharedObject { return getHouseAccessLevel(player) != HOUSE_NOT_INVITED; } - AccessHouseLevel_t getHouseAccessLevel(std::shared_ptr<Player> player) const; - bool kickPlayer(std::shared_ptr<Player> player, std::shared_ptr<Player> target); + AccessHouseLevel_t getHouseAccessLevel(const std::shared_ptr<Player> &player) const; + bool kickPlayer(const std::shared_ptr<Player> &player, const std::shared_ptr<Player> &target); void setEntryPos(Position pos) { posEntry = pos; @@ -126,7 +126,7 @@ class House : public SharedObject { } void setName(std::string newHouseName) { - this->houseName = newHouseName; + this->houseName = std::move(newHouseName); } const std::string &getName() const { return houseName; @@ -148,8 +148,8 @@ class House : public SharedObject { */ void setNewOwnerGuid(int32_t newOwnerGuid, bool serverStartup); void clearHouseInfo(bool preventOwnerDeletion); - bool tryTransferOwnership(std::shared_ptr<Player> player, bool serverStartup); - void setOwner(uint32_t guid, bool updateDatabase = true, std::shared_ptr<Player> player = nullptr); + bool tryTransferOwnership(const std::shared_ptr<Player> &player, bool serverStartup); + void setOwner(uint32_t guid, bool updateDatabase = true, const std::shared_ptr<Player> &player = nullptr); uint32_t getOwner() const { return owner; } @@ -192,14 +192,14 @@ class House : public SharedObject { return id; } - void addDoor(std::shared_ptr<Door> door); - void removeDoor(std::shared_ptr<Door> door); + void addDoor(const std::shared_ptr<Door> &door); + void removeDoor(const std::shared_ptr<Door> &door); std::shared_ptr<Door> getDoorByNumber(uint32_t doorId) const; - std::shared_ptr<Door> getDoorByPosition(const Position &pos); + std::shared_ptr<Door> getDoorByPosition(const Position &pos) const; std::shared_ptr<HouseTransferItem> getTransferItem(); void resetTransferItem(); - bool executeTransfer(std::shared_ptr<HouseTransferItem> item, std::shared_ptr<Player> player); + bool executeTransfer(const std::shared_ptr<HouseTransferItem> &item, const std::shared_ptr<Player> &player); const HouseTileList &getTiles() const { return houseTiles; @@ -209,8 +209,8 @@ class House : public SharedObject { return doorList; } - void addBed(std::shared_ptr<BedItem> bed); - void removeBed(std::shared_ptr<BedItem> bed); + void addBed(const std::shared_ptr<BedItem> &bed); + void removeBed(const std::shared_ptr<BedItem> &bed); const HouseBedItemList &getBeds() const { return bedsList; } @@ -226,8 +226,8 @@ class House : public SharedObject { return maxBeds; } - bool transferToDepot(std::shared_ptr<Player> player) const; - bool transferToDepot(std::shared_ptr<Player> player, std::shared_ptr<HouseTile> tile) const; + bool transferToDepot(const std::shared_ptr<Player> &player) const; + bool transferToDepot(const std::shared_ptr<Player> &player, const std::shared_ptr<HouseTile> &tile) const; bool hasItemOnTile() const; bool hasNewOwnership() const; @@ -268,8 +268,8 @@ class House : public SharedObject { bool isLoaded = false; - void handleContainer(ItemList &moveItemList, std::shared_ptr<Item> item) const; - void handleWrapableItem(ItemList &moveItemList, std::shared_ptr<Item> item, std::shared_ptr<Player> player, std::shared_ptr<HouseTile> houseTile) const; + void handleContainer(ItemList &moveItemList, const std::shared_ptr<Item> &item) const; + void handleWrapableItem(ItemList &moveItemList, const std::shared_ptr<Item> &item, const std::shared_ptr<Player> &player, const std::shared_ptr<HouseTile> &houseTile) const; }; using HouseMap = std::map<uint32_t, std::shared_ptr<House>>; @@ -284,7 +284,7 @@ class Houses { Houses &operator=(const Houses &) = delete; std::shared_ptr<House> addHouse(uint32_t id) { - if (auto it = houseMap.find(id); it != houseMap.end()) { + if (const auto it = houseMap.find(id); it != houseMap.end()) { return it->second; } @@ -292,14 +292,14 @@ class Houses { } std::shared_ptr<House> getHouse(uint32_t houseId) { - auto it = houseMap.find(houseId); + const auto it = houseMap.find(houseId); if (it == houseMap.end()) { return nullptr; } return it->second; } - std::shared_ptr<House> getHouseByPlayerId(uint32_t playerId); + std::shared_ptr<House> getHouseByPlayerId(uint32_t playerId) const; bool loadHousesXML(const std::string &filename); diff --git a/src/map/house/housetile.cpp b/src/map/house/housetile.cpp index d43be459ee2..71d6ee241ed 100644 --- a/src/map/house/housetile.cpp +++ b/src/map/house/housetile.cpp @@ -7,64 +7,71 @@ * Website: https://docs.opentibiabr.com/ */ -#include "items/tile.hpp" -#include "creatures/monsters/monster.hpp" #include "map/house/housetile.hpp" -#include "map/house/house.hpp" + +#include "config/configmanager.hpp" +#include "creatures/monsters/monster.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" +#include "items/tile.hpp" +#include "map/house/house.hpp" +#include "utils/tools.hpp" + +HouseTile::HouseTile(const Position &position, std::shared_ptr<House> newHouse) : + DynamicTile(position.x, position.y, position.z), house(std::move(newHouse)) { } HouseTile::HouseTile(int32_t initX, int32_t initY, int32_t initZ, std::shared_ptr<House> initHouse) : - DynamicTile(initX, initY, initZ), house(initHouse) { } + DynamicTile(initX, initY, initZ), house(std::move(initHouse)) { } -void HouseTile::addThing(int32_t index, std::shared_ptr<Thing> thing) { +void HouseTile::addThing(int32_t index, const std::shared_ptr<Thing> &thing) { Tile::addThing(index, thing); if (!thing || !thing->getParent()) { return; } - if (std::shared_ptr<Item> item = thing->getItem()) { + if (const auto &item = thing->getItem()) { updateHouse(item); } } -void HouseTile::internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) { +void HouseTile::internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) { Tile::internalAddThing(index, thing); if (!thing || !thing->getParent()) { return; } - if (std::shared_ptr<Item> item = thing->getItem()) { + if (const auto &item = thing->getItem()) { updateHouse(item); } } -void HouseTile::updateHouse(std::shared_ptr<Item> item) { +void HouseTile::updateHouse(const std::shared_ptr<Item> &item) const { if (item->getParent().get() != this) { return; } - std::shared_ptr<Door> door = item->getDoor(); + const auto &door = item->getDoor(); if (door) { if (door->getDoorId() != 0) { house->addDoor(door); } } else { - std::shared_ptr<BedItem> bed = item->getBed(); + const auto &bed = item->getBed(); if (bed) { house->addBed(bed); } } } -ReturnValue HouseTile::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, std::shared_ptr<Creature> actor /* = nullptr*/) { - if (std::shared_ptr<Creature> creature = thing->getCreature()) { - if (std::shared_ptr<Player> player = creature->getPlayer()) { +ReturnValue HouseTile::queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t tileFlags, const std::shared_ptr<Creature> &actor /* = nullptr*/) { + if (const auto &creature = thing->getCreature()) { + if (const auto &player = creature->getPlayer()) { if (!house->isInvited(player)) { return RETURNVALUE_PLAYERISNOTINVITED; } - } else if (std::shared_ptr<Monster> monster = creature->getMonster()) { + } else if (const auto &monster = creature->getMonster()) { if (monster->isSummon()) { if (!house->isInvited(monster->getMaster()->getPlayer())) { return RETURNVALUE_NOTPOSSIBLE; @@ -77,7 +84,7 @@ ReturnValue HouseTile::queryAdd(int32_t index, const std::shared_ptr<Thing> &thi } } } else if (thing->getItem() && actor) { - std::shared_ptr<Player> actorPlayer = actor->getPlayer(); + const auto &actorPlayer = actor->getPlayer(); if (house && (!house->isInvited(actorPlayer) || house->getHouseAccessLevel(actorPlayer) == HOUSE_GUEST) && g_configManager().getBoolean(ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS)) { return RETURNVALUE_CANNOTTHROW; } @@ -85,12 +92,12 @@ ReturnValue HouseTile::queryAdd(int32_t index, const std::shared_ptr<Thing> &thi return Tile::queryAdd(index, thing, count, tileFlags, actor); } -std::shared_ptr<Cylinder> HouseTile::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &tileFlags) { - if (std::shared_ptr<Creature> creature = thing->getCreature()) { - if (std::shared_ptr<Player> player = creature->getPlayer()) { +std::shared_ptr<Cylinder> HouseTile::queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &tileFlags) { + if (const auto &creature = thing->getCreature()) { + if (const auto &player = creature->getPlayer()) { if (!house->isInvited(player)) { const Position &entryPos = house->getEntryPosition(); - std::shared_ptr<Tile> destTile = g_game().map.getTile(entryPos); + auto destTile = g_game().map.getTile(entryPos); if (!destTile) { g_logger().error("[HouseTile::queryDestination] - " "Entry not correct for house name: {} " @@ -103,7 +110,7 @@ std::shared_ptr<Cylinder> HouseTile::queryDestination(int32_t &index, const std: } index = -1; - *destItem = nullptr; + destItem = nullptr; return destTile; } } @@ -112,14 +119,14 @@ std::shared_ptr<Cylinder> HouseTile::queryDestination(int32_t &index, const std: return Tile::queryDestination(index, thing, destItem, tileFlags); } -ReturnValue HouseTile::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor /*= nullptr*/) { - std::shared_ptr<Item> item = thing->getItem(); +ReturnValue HouseTile::queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor /*= nullptr */) { + const auto &item = thing->getItem(); if (!item) { return RETURNVALUE_NOTPOSSIBLE; } if (actor && g_configManager().getBoolean(ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS)) { - std::shared_ptr<Player> actorPlayer = actor->getPlayer(); + const auto &actorPlayer = actor->getPlayer(); if (house && !house->isInvited(actorPlayer)) { return RETURNVALUE_NOTPOSSIBLE; } else if (house && house->getHouseAccessLevel(actorPlayer) == HOUSE_GUEST) { diff --git a/src/map/house/housetile.hpp b/src/map/house/housetile.hpp index b661251dbea..293fc0074ee 100644 --- a/src/map/house/housetile.hpp +++ b/src/map/house/housetile.hpp @@ -15,24 +15,27 @@ class House; class HouseTile final : public DynamicTile { public: + using Tile::addThing; + + HouseTile(const Position &position, std::shared_ptr<House> house); HouseTile(int32_t x, int32_t y, int32_t z, std::shared_ptr<House> house); // cylinder implementations - ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryAdd(int32_t index, const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item>* destItem, uint32_t &flags) override; + std::shared_ptr<Cylinder> queryDestination(int32_t &index, const std::shared_ptr<Thing> &thing, std::shared_ptr<Item> &destItem, uint32_t &flags) override; - ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, std::shared_ptr<Creature> actor = nullptr) override; + ReturnValue queryRemove(const std::shared_ptr<Thing> &thing, uint32_t count, uint32_t flags, const std::shared_ptr<Creature> &actor = nullptr) override; - void addThing(int32_t index, std::shared_ptr<Thing> thing) override; - void virtual internalAddThing(uint32_t index, std::shared_ptr<Thing> thing) override; + void addThing(int32_t index, const std::shared_ptr<Thing> &thing) override; + void internalAddThing(uint32_t index, const std::shared_ptr<Thing> &thing) override; std::shared_ptr<House> getHouse() override { return house; } private: - void updateHouse(std::shared_ptr<Item> item); + void updateHouse(const std::shared_ptr<Item> &item) const; std::shared_ptr<House> house; }; diff --git a/src/map/map.cpp b/src/map/map.cpp index 4647deed66c..8cb17c01752 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -7,18 +7,19 @@ * Website: https://docs.opentibiabr.com/ */ -#include "map.hpp" -#include "utils/astarnodes.hpp" +#include "map/map.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" #include "creatures/monsters/monster.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" +#include "game/scheduling/dispatcher.hpp" #include "game/zones/zone.hpp" #include "io/iomap.hpp" #include "io/iomapserialize.hpp" -#include "game/scheduling/dispatcher.hpp" +#include "lua/callbacks/event_callback.hpp" +#include "lua/callbacks/events_callbacks.hpp" #include "map/spectators.hpp" +#include "utils/astarnodes.hpp" void Map::load(const std::string &identifier, const Position &pos) { try { @@ -163,7 +164,7 @@ std::shared_ptr<Tile> Map::getLoadedTile(uint16_t x, uint16_t y, uint8_t z) { return nullptr; } - const auto leaf = getMapSector(x, y); + const auto &leaf = getMapSector(x, y); if (!leaf) { return nullptr; } @@ -173,7 +174,7 @@ std::shared_ptr<Tile> Map::getLoadedTile(uint16_t x, uint16_t y, uint8_t z) { return nullptr; } - const auto tile = floor->getTile(x, y); + const auto &tile = floor->getTile(x, y); return tile; } @@ -182,7 +183,7 @@ std::shared_ptr<Tile> Map::getTile(uint16_t x, uint16_t y, uint8_t z) { return nullptr; } - const auto sector = getMapSector(x, y); + const auto §or = getMapSector(x, y); if (!sector) { return nullptr; } @@ -196,7 +197,7 @@ std::shared_ptr<Tile> Map::getTile(uint16_t x, uint16_t y, uint8_t z) { } void Map::refreshZones(uint16_t x, uint16_t y, uint8_t z) { - const auto tile = getLoadedTile(x, y, z); + const auto &tile = getLoadedTile(x, y, z); if (!tile) { return; } @@ -208,21 +209,21 @@ void Map::refreshZones(uint16_t x, uint16_t y, uint8_t z) { } } -void Map::setTile(uint16_t x, uint16_t y, uint8_t z, std::shared_ptr<Tile> newTile) { +void Map::setTile(uint16_t x, uint16_t y, uint8_t z, const std::shared_ptr<Tile> &newTile) { if (z >= MAP_MAX_LAYERS) { g_logger().error("Attempt to set tile on invalid coordinate: {}", Position(x, y, z).toString()); return; } - if (const auto sector = getMapSector(x, y)) { + if (const auto §or = getMapSector(x, y)) { sector->createFloor(z)->setTile(x, y, newTile); } else { getBestMapSector(x, y)->createFloor(z)->setTile(x, y, newTile); } } -bool Map::placeCreature(const Position ¢erPos, std::shared_ptr<Creature> creature, bool extendedPos /* = false*/, bool forceLogin /* = false*/) { - auto monster = creature->getMonster(); +bool Map::placeCreature(const Position ¢erPos, const std::shared_ptr<Creature> &creature, bool extendedPos /* = false*/, bool forceLogin /* = false*/) { + const auto &monster = creature ? creature->getMonster() : nullptr; if (monster) { monster->ignoreFieldDamage = true; } @@ -230,7 +231,7 @@ bool Map::placeCreature(const Position ¢erPos, std::shared_ptr<Creature> cre bool foundTile; bool placeInPZ; - std::shared_ptr<Tile> tile = getTile(centerPos.x, centerPos.y, centerPos.z); + auto tile = getTile(centerPos.x, centerPos.y, centerPos.z); if (tile) { placeInPZ = tile->hasFlag(TILESTATE_PROTECTIONZONE); ReturnValue ret = tile->queryAdd(0, creature, 1, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREFIELDDAMAGE); @@ -269,11 +270,11 @@ bool Map::placeCreature(const Position ¢erPos, std::shared_ptr<Creature> cre std::shuffle(relList.begin(), relList.begin() + 4, getRandomGenerator()); std::shuffle(relList.begin() + 4, relList.end(), getRandomGenerator()); } else { - std::shuffle(relList.begin(), relList.end(), getRandomGenerator()); + std::ranges::shuffle(relList, getRandomGenerator()); } - for (const auto &it : relList) { - Position tryPos(centerPos.x + it.first, centerPos.y + it.second, centerPos.z); + for (const auto &[xOffset, yOffset] : relList) { + Position tryPos(centerPos.x + xOffset, centerPos.y + yOffset, centerPos.z); tile = getTile(tryPos.x, tryPos.y, tryPos.z); if (!tile || (placeInPZ && !tile->hasFlag(TILESTATE_PROTECTIONZONE))) { @@ -310,11 +311,13 @@ bool Map::placeCreature(const Position ¢erPos, std::shared_ptr<Creature> cre uint32_t flags = 0; std::shared_ptr<Item> toItem = nullptr; - auto toCylinder = tile->queryDestination(index, creature, &toItem, flags); - toCylinder->internalAddThing(creature); + if (tile) { + const auto toCylinder = tile->queryDestination(index, creature, toItem, flags); + toCylinder->internalAddThing(creature); - const Position &dest = toCylinder->getPosition(); - getMapSector(dest.x, dest.y)->addCreature(creature); + const Position &dest = toCylinder->getPosition(); + getMapSector(dest.x, dest.y)->addCreature(creature); + } return true; } @@ -339,11 +342,11 @@ void Map::moveCreature(const std::shared_ptr<Creature> &creature, const std::sha const auto &fromZones = oldTile->getZones(); const auto &toZones = newTile->getZones(); - if (auto ret = g_game().beforeCreatureZoneChange(creature, fromZones, toZones); ret != RETURNVALUE_NOERROR) { + if (const auto &ret = g_game().beforeCreatureZoneChange(creature, fromZones, toZones); ret != RETURNVALUE_NOERROR) { return; } - bool teleport = forceTeleport || !newTile->getGround() || !Position::areInRange<1, 1, 0>(oldPos, newPos); + const bool teleport = forceTeleport || !newTile->getGround() || !Position::areInRange<1, 1, 0>(oldPos, newPos); Spectators spectators; if (!teleport && oldPos.z == newPos.z) { @@ -370,7 +373,7 @@ void Map::moveCreature(const std::shared_ptr<Creature> &creature, const std::sha spectators.find<Creature>(newPos, true, 0, 0, 0, 0, false); } - auto playersSpectators = spectators.filter<Player>(); + const auto playersSpectators = spectators.filter<Player>(); std::vector<int32_t> oldStackPosVector; oldStackPosVector.reserve(playersSpectators.size()); @@ -415,7 +418,7 @@ void Map::moveCreature(const std::shared_ptr<Creature> &creature, const std::sha size_t i = 0; for (const auto &spectator : playersSpectators) { // Use the correct stackpos - int32_t stackpos = oldStackPosVector[i++]; + const int32_t stackpos = oldStackPosVector[i++]; if (stackpos != -1) { const auto &player = spectator->getPlayer(); player->sendCreatureMove(creature, newPos, newTile->getStackposOfCreature(player, creature), oldPos, stackpos, teleport); @@ -439,6 +442,13 @@ void Map::moveCreature(const std::shared_ptr<Creature> &creature, const std::sha } else { events(); } + + if (forceTeleport) { + if (const auto &player = creature->getPlayer()) { + player->sendMagicEffect(oldPos, CONST_ME_TELEPORT); + player->sendMagicEffect(newPos, CONST_ME_TELEPORT); + } + } } bool Map::canThrowObjectTo(const Position &fromPos, const Position &toPos, const SightLines_t lineOfSight /*= SightLine_CheckSightLine*/, const int32_t rangex /*= Map::maxClientViewportX*/, const int32_t rangey /*= Map::maxClientViewportY*/) { @@ -449,7 +459,7 @@ bool Map::canThrowObjectTo(const Position &fromPos, const Position &toPos, const return false; } - int32_t deltaz = Position::getDistanceZ(fromPos, toPos); + const int32_t deltaz = Position::getDistanceZ(fromPos, toPos); if (deltaz > MAP_LAYER_VIEW_LIMIT) { return false; } @@ -630,17 +640,6 @@ std::shared_ptr<Tile> Map::canWalkTo(const std::shared_ptr<Creature> &creature, return nullptr; } - const int32_t walkCache = creature->getWalkCache(pos); - - if (walkCache == 0) { - return nullptr; - } - - if (walkCache == 1) { - return getTile(pos.x, pos.y, pos.z); - } - - // used for non-cached tiles const auto &tile = getTile(pos.x, pos.y, pos.z); if (creature->getTile() != tile) { if (!tile || tile->queryAdd(0, creature, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) != RETURNVALUE_NOERROR) { @@ -651,7 +650,7 @@ std::shared_ptr<Tile> Map::canWalkTo(const std::shared_ptr<Creature> &creature, return tile; } -bool Map::getPathMatching(const std::shared_ptr<Creature> &creature, const Position &__targetPos, std::vector<Direction> &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { +bool Map::getPathMatching(const std::shared_ptr<Creature> &creature, const Position &_targetPos, std::vector<Direction> &dirList, const FrozenPathingConditionCall &pathCondition, const FindPathParams &fpp) { static int_fast32_t allNeighbors[8][2] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } }; @@ -669,7 +668,7 @@ bool Map::getPathMatching(const std::shared_ptr<Creature> &creature, const Posit const bool withoutCreature = creature == nullptr; - Position pos = withoutCreature ? __targetPos : creature->getPosition(); + Position pos = withoutCreature ? _targetPos : creature->getPosition(); Position endPos; AStarNodes nodes(pos.x, pos.y, AStarNodes::getTileWalkCost(creature, getTile(pos.x, pos.y, pos.z))); @@ -677,14 +676,14 @@ bool Map::getPathMatching(const std::shared_ptr<Creature> &creature, const Posit int32_t bestMatch = 0; const auto &startPos = pos; - const auto &targetPos = withoutCreature ? pathCondition.getTargetPos() : __targetPos; + const auto &targetPos = withoutCreature ? pathCondition.getTargetPos() : _targetPos; const int_fast32_t sX = std::abs(targetPos.getX() - pos.getX()); const int_fast32_t sY = std::abs(targetPos.getY() - pos.getY()); uint_fast16_t cntDirs = 0; - AStarNode* found = nullptr; + const AStarNode* found = nullptr; do { AStarNode* n = nodes.getBestNode(); if (!n) { @@ -798,8 +797,8 @@ bool Map::getPathMatching(const std::shared_ptr<Creature> &creature, const Posit pos.x = found->x; pos.y = found->y; - int_fast32_t dx = pos.getX() - prevx; - int_fast32_t dy = pos.getY() - prevy; + const int_fast32_t dx = pos.getX() - prevx; + const int_fast32_t dy = pos.getY() - prevy; prevx = pos.x; prevy = pos.y; @@ -864,7 +863,7 @@ bool Map::getPathMatchingCond(const std::shared_ptr<Creature> &creature, const P uint_fast16_t cntDirs = 0; - AStarNode* found = nullptr; + const AStarNode* found = nullptr; do { AStarNode* n = nodes.getBestNode(); if (!n) { @@ -986,8 +985,8 @@ bool Map::getPathMatchingCond(const std::shared_ptr<Creature> &creature, const P pos.x = found->x; pos.y = found->y; - int_fast32_t dx = pos.getX() - prevx; - int_fast32_t dy = pos.getY() - prevy; + const int_fast32_t dx = pos.getX() - prevx; + const int_fast32_t dy = pos.getY() - prevy; prevx = pos.x; prevy = pos.y; @@ -1018,8 +1017,8 @@ bool Map::getPathMatchingCond(const std::shared_ptr<Creature> &creature, const P return true; } -uint32_t Map::clean() { - uint64_t start = OTSYS_TIME(); +uint32_t Map::clean() const { + const uint64_t start = OTSYS_TIME(); size_t qntTiles = 0; if (g_game().getGameState() == GAME_STATE_NORMAL) { @@ -1034,7 +1033,7 @@ uint32_t Map::clean() { continue; } - if (const auto items = tile->getItemList()) { + if (const auto &items = tile->getItemList()) { ++qntTiles; for (const auto &item : *items) { if (item->isCleanable()) { @@ -1055,7 +1054,7 @@ uint32_t Map::clean() { g_game().setGameState(GAME_STATE_NORMAL); } - uint64_t end = OTSYS_TIME(); + const uint64_t end = OTSYS_TIME(); g_logger().info("CLEAN: Removed {} item{} from {} tile{} in {} seconds", count, (count != 1 ? "s" : ""), qntTiles, (qntTiles != 1 ? "s" : ""), (end - start) / (1000.f)); return count; } diff --git a/src/map/map.hpp b/src/map/map.hpp index f6e38cb3eac..b4b78c7b5f4 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -29,9 +29,9 @@ class FrozenPathingConditionCall; * Map class. * Holds all the actual map-data */ -class Map : public MapCache { +class Map final : public MapCache { public: - uint32_t clean(); + uint32_t clean() const; std::filesystem::path getPath() const { return path; @@ -59,7 +59,7 @@ class Map : public MapCache { * \param loadNpcs if true, the map custom npcs is loaded * \returns true if the custom map was loaded successfully */ - void loadMapCustom(const std::string &mapName, bool loadHouses, bool loadMonsters, bool loadNpcs, bool loadZones, const int customMapIndex); + void loadMapCustom(const std::string &mapName, bool loadHouses, bool loadMonsters, bool loadNpcs, bool loadZones, int customMapIndex); void loadHouseInfo(); @@ -95,7 +95,7 @@ class Map : public MapCache { * \param extendedPos If true, the creature will in first-hand be placed 2 tiles away * \param forceLogin If true, placing the creature will not fail becase of obstacles (creatures/chests) */ - bool placeCreature(const Position ¢erPos, std::shared_ptr<Creature> creature, bool extendedPos = false, bool forceLogin = false); + bool placeCreature(const Position ¢erPos, const std::shared_ptr<Creature> &creature, bool extendedPos = false, bool forceLogin = false); void moveCreature(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, bool forceTeleport = false); @@ -147,8 +147,8 @@ class Map : public MapCache { /** * Set a single tile. */ - void setTile(uint16_t x, uint16_t y, uint8_t z, std::shared_ptr<Tile> newTile); - void setTile(const Position &pos, std::shared_ptr<Tile> newTile) { + void setTile(uint16_t x, uint16_t y, uint8_t z, const std::shared_ptr<Tile> &newTile); + void setTile(const Position &pos, const std::shared_ptr<Tile> &newTile) { setTile(pos.x, pos.y, pos.z, newTile); } std::shared_ptr<Tile> getLoadedTile(uint16_t x, uint16_t y, uint8_t z); diff --git a/src/map/mapcache.cpp b/src/map/mapcache.cpp index bad1315113c..f505c544fe2 100644 --- a/src/map/mapcache.cpp +++ b/src/map/mapcache.cpp @@ -7,20 +7,17 @@ * Website: https://docs.opentibiabr.com/ */ -#include "mapcache.hpp" +#include "map/mapcache.hpp" #include "game/movement/teleport.hpp" #include "game/scheduling/dispatcher.hpp" -#include "items/bed.hpp" -#include "io/iologindata.hpp" -#include "items/item.hpp" -#include "game/game.hpp" #include "game/zones/zone.hpp" -#include "map/map.hpp" -#include "utils/hash.hpp" #include "io/filestream.hpp" - #include "io/iomap.hpp" +#include "items/containers/depot/depotlocker.hpp" +#include "items/item.hpp" +#include "map/map.hpp" +#include "utils/hash.hpp" static phmap::flat_hash_map<size_t, std::shared_ptr<BasicItem>> items; static phmap::flat_hash_map<size_t, std::shared_ptr<BasicTile>> tiles; @@ -33,12 +30,12 @@ std::shared_ptr<BasicTile> static_tryGetTileFromCache(const std::shared_ptr<Basi return ref ? tiles.try_emplace(ref->hash(), ref).first->second : nullptr; } -void MapCache::flush() { +void MapCache::flush() const { items.clear(); tiles.clear(); } -void MapCache::parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, std::shared_ptr<Item> item) { +void MapCache::parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, const std::shared_ptr<Item> &item) const { if (BasicItem->charges > 0) { item->setSubType(BasicItem->charges); } @@ -52,7 +49,7 @@ void MapCache::parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, std::s } if (item->getTeleport() && (BasicItem->destX != 0 || BasicItem->destY != 0 || BasicItem->destZ != 0)) { - auto dest = Position(BasicItem->destX, BasicItem->destY, BasicItem->destZ); + const auto dest = Position(BasicItem->destX, BasicItem->destY, BasicItem->destZ); item->getTeleport()->setDestPos(dest); } @@ -73,7 +70,7 @@ void MapCache::parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, std::s } std::shared_ptr<Item> MapCache::createItem(const std::shared_ptr<BasicItem> &BasicItem, Position position) { - auto item = Item::CreateItem(BasicItem->id, position); + const auto &item = Item::CreateItem(BasicItem->id, position); if (!item) { return nullptr; } @@ -102,18 +99,15 @@ std::shared_ptr<Item> MapCache::createItem(const std::shared_ptr<BasicItem> &Bas return item; } -std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<Floor> &floor, uint16_t x, uint16_t y) { - const auto cachedTile = floor->getTileCache(x, y); +std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::shared_ptr<Floor> &floor, uint16_t x, uint16_t y) { + const auto &cachedTile = floor->getTileCache(x, y); const auto oldTile = floor->getTile(x, y); if (!cachedTile) { return oldTile; } - std::unique_lock l(floor->getMutex()); - const uint8_t z = floor->getZ(); - - auto map = static_cast<Map*>(this); + const auto map = dynamic_cast<Map*>(this); std::vector<std::shared_ptr<Creature>> oldCreatureList; if (oldTile) { @@ -125,20 +119,22 @@ std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<F } std::shared_ptr<Tile> tile = nullptr; - if (cachedTile->isHouse()) { - const auto house = map->houses.getHouse(cachedTile->houseId); - tile = std::make_shared<HouseTile>(x, y, z, house); - house->addTile(std::static_pointer_cast<HouseTile>(tile)); - } else if (cachedTile->isStatic) { - tile = std::make_shared<StaticTile>(x, y, z); - } else { - tile = std::make_shared<DynamicTile>(x, y, z); - } auto pos = Position(x, y, z); - for (const auto &creature : oldCreatureList) { - tile->internalAddThing(creature); + if (cachedTile->isHouse()) { + if (const auto &house = map->houses.getHouse(cachedTile->houseId)) { + tile = std::make_shared<HouseTile>(pos, house); + tile->safeCall([tile] { + tile->getHouse()->addTile(tile->static_self_cast<HouseTile>()); + }); + } else { + g_logger().error("[{}] house not found for houseId {}", std::source_location::current().function_name(), cachedTile->houseId); + } + } else if (cachedTile->isStatic) { + tile = std::make_shared<StaticTile>(pos); + } else { + tile = std::make_shared<DynamicTile>(pos); } if (cachedTile->ground != nullptr) { @@ -151,15 +147,15 @@ std::shared_ptr<Tile> MapCache::getOrCreateTileFromCache(const std::unique_ptr<F tile->setFlag(static_cast<TileFlags_t>(cachedTile->flags)); - // add zone synchronously - g_dispatcher().context().tryAddEvent( - [tile, pos] { - for (const auto &zone : Zone::getZones(pos)) { - tile->addZone(zone); - } - }, - "Zone::getZones" - ); + tile->safeCall([tile, pos, movedOldCreatureList = std::move(oldCreatureList)]() { + for (const auto &creature : movedOldCreatureList) { + tile->internalAddThing(creature); + } + + for (const auto &zone : Zone::getZones(pos)) { + tile->addZone(zone); + } + }); floor->setTile(x, y, tile); @@ -175,7 +171,7 @@ void MapCache::setBasicTile(uint16_t x, uint16_t y, uint8_t z, const std::shared return; } - const auto tile = static_tryGetTileFromCache(newTile); + const auto &tile = static_tryGetTileFromCache(newTile); if (const auto sector = getMapSector(x, y)) { sector->createFloor(z)->setTileCache(x, y, tile); } else { @@ -183,7 +179,7 @@ void MapCache::setBasicTile(uint16_t x, uint16_t y, uint8_t z, const std::shared } } -std::shared_ptr<BasicItem> MapCache::tryReplaceItemFromCache(const std::shared_ptr<BasicItem> &ref) { +std::shared_ptr<BasicItem> MapCache::tryReplaceItemFromCache(const std::shared_ptr<BasicItem> &ref) const { return static_tryGetItemFromCache(ref); } @@ -228,7 +224,7 @@ MapSector* MapCache::getBestMapSector(uint32_t x, uint32_t y) { } void BasicTile::hash(size_t &h) const { - std::array<uint32_t, 4> arr = { flags, houseId, type, isStatic }; + const std::array<uint32_t, 4> arr = { flags, houseId, type, isStatic }; for (const auto v : arr) { if (v > 0) { stdext::hash_combine(h, v); diff --git a/src/map/mapcache.hpp b/src/map/mapcache.hpp index 429d786972b..eb7a313ffab 100644 --- a/src/map/mapcache.hpp +++ b/src/map/mapcache.hpp @@ -15,7 +15,7 @@ class Map; class Tile; class Item; -class Position; +struct Position; class FileStream; #pragma pack(1) @@ -47,7 +47,7 @@ struct BasicItem { private: void hash(size_t &h) const; - friend class BasicTile; + friend struct BasicTile; }; struct BasicTile { @@ -85,9 +85,9 @@ class MapCache { void setBasicTile(uint16_t x, uint16_t y, uint8_t z, const std::shared_ptr<BasicTile> &BasicTile); - std::shared_ptr<BasicItem> tryReplaceItemFromCache(const std::shared_ptr<BasicItem> &ref); + std::shared_ptr<BasicItem> tryReplaceItemFromCache(const std::shared_ptr<BasicItem> &ref) const; - void flush(); + void flush() const; /** * Creates a map sector. @@ -111,11 +111,11 @@ class MapCache { } protected: - std::shared_ptr<Tile> getOrCreateTileFromCache(const std::unique_ptr<Floor> &floor, uint16_t x, uint16_t y); + std::shared_ptr<Tile> getOrCreateTileFromCache(const std::shared_ptr<Floor> &floor, uint16_t x, uint16_t y); std::unordered_map<uint32_t, MapSector> mapSectors; private: - void parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, std::shared_ptr<Item> item); + void parseItemAttr(const std::shared_ptr<BasicItem> &BasicItem, const std::shared_ptr<Item> &item) const; std::shared_ptr<Item> createItem(const std::shared_ptr<BasicItem> &BasicItem, Position position); }; diff --git a/src/map/spectators.cpp b/src/map/spectators.cpp index 85976503d69..6a3ca09c513 100644 --- a/src/map/spectators.cpp +++ b/src/map/spectators.cpp @@ -7,7 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ -#include "spectators.hpp" +#include "map/spectators.hpp" + +#include "creatures/creature.hpp" #include "game/game.hpp" phmap::flat_hash_map<Position, SpectatorsCache> Spectators::spectatorsCache; @@ -39,7 +41,7 @@ Spectators Spectators::insertAll(const CreatureVector &list) { return *this; } -bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, const Position ¢erPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) { +bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, bool onlyMonsters, bool onlyNpcs, const Position ¢erPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) { const auto &list = multifloor || !specData.floor ? specData.multiFloor : specData.floor; if (!list) { @@ -56,12 +58,15 @@ bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onl spectators.reserve(creatures.size()); for (const auto &creature : *list) { const auto &specPos = creature->getPosition(); - if (centerPos.x - specPos.x >= minRangeX - && centerPos.y - specPos.y >= minRangeY - && centerPos.x - specPos.x <= maxRangeX - && centerPos.y - specPos.y <= maxRangeY - && (multifloor || specPos.z == centerPos.z) - && (!onlyPlayers || creature->getPlayer())) { + if ((centerPos.x - specPos.x >= minRangeX + && centerPos.y - specPos.y >= minRangeY + && centerPos.x - specPos.x <= maxRangeX + && centerPos.y - specPos.y <= maxRangeY + && (multifloor || specPos.z == centerPos.z) + && ((onlyPlayers && creature->getPlayer()) + || (onlyMonsters && creature->getMonster()) + || (onlyNpcs && creature->getNpc())) + || (!onlyPlayers && !onlyMonsters && !onlyNpcs))) { spectators.emplace_back(creature); } } @@ -73,7 +78,7 @@ bool Spectators::checkCache(const SpectatorsCache::FloorData &specData, bool onl return true; } -CreatureVector Spectators::getSpectators(const Position ¢erPos, bool multifloor, bool onlyPlayers, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) { +CreatureVector Spectators::getSpectators(const Position ¢erPos, bool multifloor, bool onlyPlayers, bool onlyMonsters, bool onlyNpcs, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY) { uint8_t minRangeZ = centerPos.z; uint8_t maxRangeZ = centerPos.z; @@ -124,8 +129,12 @@ CreatureVector Spectators::getSpectators(const Position ¢erPos, bool multifl const MapSector* sectorE = sectorS; for (int32_t nx = startx1; nx <= endx2; nx += SECTOR_SIZE) { if (sectorE) { - const auto &node_list = onlyPlayers ? sectorE->player_list : sectorE->creature_list; - for (const auto &creature : node_list) { + const auto &nodeList = onlyPlayers ? sectorE->player_list + : onlyMonsters ? sectorE->monster_list + : onlyNpcs ? sectorE->npc_list + : sectorE->creature_list; + + for (const auto &creature : nodeList) { const auto &cpos = creature->getPosition(); if (static_cast<uint32_t>(static_cast<int32_t>(cpos.z) - minRangeZ) <= depth) { const int_fast16_t offsetZ = Position::getOffsetZ(centerPos, cpos); @@ -150,14 +159,14 @@ CreatureVector Spectators::getSpectators(const Position ¢erPos, bool multifl return spectators; } -Spectators Spectators::find(const Position ¢erPos, bool multifloor, bool onlyPlayers, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, bool useCache) { +Spectators Spectators::find(const Position ¢erPos, bool multifloor, bool onlyPlayers, bool onlyMonsters, bool onlyNpcs, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, bool useCache) { minRangeX = (minRangeX == 0 ? -MAP_MAX_VIEW_PORT_X : -minRangeX); maxRangeX = (maxRangeX == 0 ? MAP_MAX_VIEW_PORT_X : maxRangeX); minRangeY = (minRangeY == 0 ? -MAP_MAX_VIEW_PORT_Y : -minRangeY); maxRangeY = (maxRangeY == 0 ? MAP_MAX_VIEW_PORT_Y : maxRangeY); if (!useCache) { - insertAll(getSpectators(centerPos, multifloor, onlyPlayers, minRangeX, maxRangeX, minRangeY, maxRangeY)); + insertAll(getSpectators(centerPos, multifloor, onlyPlayers, onlyMonsters, onlyNpcs, minRangeX, maxRangeX, minRangeY, maxRangeY)); return *this; } @@ -174,29 +183,38 @@ Spectators Spectators::find(const Position ¢erPos, bool multifloor, bool onl } else { const bool checkDistance = minRangeX != cache.minRangeX || maxRangeX != cache.maxRangeX || minRangeY != cache.minRangeY || maxRangeY != cache.maxRangeY; - if (onlyPlayers) { - // check players cache - if (checkCache(cache.players, true, centerPos, checkDistance, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { + if (onlyPlayers || onlyMonsters || onlyNpcs) { + static const SpectatorsCache::FloorData EMPTY_FLOOR_DATA; + + const auto &creaturesCache = onlyPlayers ? cache.players + : onlyMonsters ? cache.monsters + : onlyNpcs ? cache.npcs + : EMPTY_FLOOR_DATA; + + // check players/monsters/npcs cache + if (checkCache(creaturesCache, onlyPlayers, onlyMonsters, onlyNpcs, centerPos, checkDistance, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { return *this; } - // if there is no player cache, look for players in the creatures cache. - if (checkCache(cache.creatures, true, centerPos, true, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { + // if there is no players/monsters/npcs cache, look for players/monsters/npcs in the creatures cache. + if (checkCache(cache.creatures, onlyPlayers, onlyMonsters, onlyNpcs, centerPos, true, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { return *this; } - // All Creatures - } else if (checkCache(cache.creatures, false, centerPos, checkDistance, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { + } else if (checkCache(cache.creatures, false, false, false, centerPos, checkDistance, multifloor, minRangeX, maxRangeX, minRangeY, maxRangeY)) { return *this; } } } - const auto &spectators = getSpectators(centerPos, multifloor, onlyPlayers, minRangeX, maxRangeX, minRangeY, maxRangeY); + const auto &spectators = getSpectators(centerPos, multifloor, onlyPlayers, onlyMonsters, onlyNpcs, minRangeX, maxRangeX, minRangeY, maxRangeY); // It is necessary to create the cache even if no spectators is found, so that there is no future query. - auto &cache = cacheFound ? it->second : spectatorsCache.emplace(centerPos, SpectatorsCache { .minRangeX = minRangeX, .maxRangeX = maxRangeX, .minRangeY = minRangeY, .maxRangeY = maxRangeY, .creatures = {}, .players = {} }).first->second; - auto &creaturesCache = onlyPlayers ? cache.players : cache.creatures; + auto &cache = cacheFound ? it->second : spectatorsCache.emplace(centerPos, SpectatorsCache { .minRangeX = minRangeX, .maxRangeX = maxRangeX, .minRangeY = minRangeY, .maxRangeY = maxRangeY, .creatures = {}, .monsters = {}, .npcs = {}, .players = {} }).first->second; + auto &creaturesCache = onlyPlayers ? cache.players + : onlyMonsters ? cache.monsters + : onlyNpcs ? cache.npcs + : cache.creatures; auto &creatureList = (multifloor ? creaturesCache.multiFloor : creaturesCache.floor); if (creatureList) { creatureList->clear(); @@ -212,3 +230,54 @@ Spectators Spectators::find(const Position ¢erPos, bool multifloor, bool onl return *this; } + +Spectators Spectators::excludeMaster() const { + auto specs = Spectators(); + if (creatures.empty()) { + return specs; + } + + specs.creatures.reserve(creatures.size()); + + for (const auto &c : creatures) { + if (c->getMonster() != nullptr && !c->getMaster()) { + specs.insert(c); + } + } + + return specs; +} + +Spectators Spectators::excludePlayerMaster() const { + auto specs = Spectators(); + if (creatures.empty()) { + return specs; + } + + specs.creatures.reserve(creatures.size()); + + for (const auto &c : creatures) { + if ((c->getMonster() != nullptr && !c->getMaster() || !c->getMaster()->getPlayer())) { + specs.insert(c); + } + } + + return specs; +} + +Spectators Spectators::filter(bool onlyPlayers, bool onlyMonsters, bool onlyNpcs) const { + auto specs = Spectators(); + specs.creatures.reserve(creatures.size()); + + for (const auto &c : creatures) { + if (onlyPlayers && c->getPlayer() != nullptr) { + specs.insert(c); + } else if (onlyMonsters && c->getMonster() != nullptr) { + specs.insert(c); + } else if (onlyNpcs && c->getNpc() != nullptr) { + specs.insert(c); + } + } + + return specs; +} diff --git a/src/map/spectators.hpp b/src/map/spectators.hpp index d35bc21721b..f858603a791 100644 --- a/src/map/spectators.hpp +++ b/src/map/spectators.hpp @@ -9,13 +9,15 @@ #pragma once -#include "creatures/creature.hpp" - +class Creature; class Player; class Monster; class Npc; struct Position; +// Forward declaration para CreatureVector +using CreatureVector = std::vector<std::shared_ptr<Creature>>; + struct SpectatorsCache { struct FloorData { std::optional<CreatureVector> floor; @@ -28,6 +30,8 @@ struct SpectatorsCache { int32_t maxRangeY { 0 }; FloorData creatures; + FloorData monsters; + FloorData npcs; FloorData players; }; @@ -36,15 +40,25 @@ class Spectators { static void clearCache(); template <typename T> - requires std::is_same_v<Creature, T> || std::is_same_v<Player, T> + requires std::is_base_of_v<Creature, T> Spectators find(const Position ¢erPos, bool multifloor = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0, bool useCache = true) { constexpr bool onlyPlayers = std::is_same_v<T, Player>; - return find(centerPos, multifloor, onlyPlayers, minRangeX, maxRangeX, minRangeY, maxRangeY, useCache); + constexpr bool onlyMonsters = std::is_same_v<T, Monster>; + constexpr bool onlyNpcs = std::is_same_v<T, Npc>; + return find(centerPos, multifloor, onlyPlayers, onlyMonsters, onlyNpcs, minRangeX, maxRangeX, minRangeY, maxRangeY, useCache); } template <typename T> requires std::is_base_of_v<Creature, T> - Spectators filter(); + Spectators filter() const { + constexpr bool onlyPlayers = std::is_same_v<T, Player>; + constexpr bool onlyMonsters = std::is_same_v<T, Monster>; + constexpr bool onlyNpcs = std::is_same_v<T, Npc>; + return filter(onlyPlayers, onlyMonsters, onlyNpcs); + } + + Spectators excludeMaster() const; + Spectators excludePlayerMaster() const; Spectators insert(const std::shared_ptr<Creature> &creature); Spectators insertAll(const CreatureVector &list); @@ -83,35 +97,12 @@ class Spectators { private: static phmap::flat_hash_map<Position, SpectatorsCache> spectatorsCache; - Spectators find(const Position ¢erPos, bool multifloor = false, bool onlyPlayers = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0, bool useCache = true); - CreatureVector getSpectators(const Position ¢erPos, bool multifloor = false, bool onlyPlayers = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0); + Spectators find(const Position ¢erPos, bool multifloor = false, bool onlyPlayers = false, bool onlyMonsters = false, bool onlyNpcs = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0, bool useCache = true); + CreatureVector getSpectators(const Position ¢erPos, bool multifloor = false, bool onlyPlayers = false, bool onlyMonsters = false, bool onlyNpcs = false, int32_t minRangeX = 0, int32_t maxRangeX = 0, int32_t minRangeY = 0, int32_t maxRangeY = 0); + + Spectators filter(bool onlyPlayers, bool onlyMonsters, bool onlyNpcs) const; - bool checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, const Position ¢erPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY); + bool checkCache(const SpectatorsCache::FloorData &specData, bool onlyPlayers, bool onlyMonsters, bool onlyNpcs, const Position ¢erPos, bool checkDistance, bool multifloor, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY); CreatureVector creatures; }; - -template <typename T> - requires std::is_base_of_v<Creature, T> -Spectators Spectators::filter() { - auto specs = Spectators(); - specs.creatures.reserve(creatures.size()); - - for (const auto &c : creatures) { - if constexpr (std::is_same_v<T, Player>) { - if (c->getPlayer() != nullptr) { - specs.insert(c); - } - } else if constexpr (std::is_same_v<T, Monster>) { - if (c->getMonster() != nullptr) { - specs.insert(c); - } - } else if constexpr (std::is_same_v<T, Npc>) { - if (c->getNpc() != nullptr) { - specs.insert(c); - } - } - } - - return specs; -} diff --git a/src/map/town.hpp b/src/map/town.hpp index d6529fa30ef..6dd91d388be 100644 --- a/src/map/town.hpp +++ b/src/map/town.hpp @@ -10,6 +10,7 @@ #pragma once #include "game/movement/position.hpp" +#include "utils/tools.hpp" class Town { public: @@ -55,16 +56,20 @@ class Towns { } std::shared_ptr<Town> getTown(const std::string &townName) const { - for (const auto &it : townMap) { - if (strcasecmp(townName.c_str(), it.second->getName().c_str()) == 0) { - return it.second; + for (const auto &[townId, town] : townMap) { + if (townId == 0) { + continue; + } + + if (caseInsensitiveCompare(townName, town->getName())) { + return town; } } return nullptr; } std::shared_ptr<Town> getTown(uint32_t townId) const { - auto it = townMap.find(townId); + const auto it = townMap.find(townId); if (it == townMap.end()) { return nullptr; } diff --git a/src/map/utils/astarnodes.cpp b/src/map/utils/astarnodes.cpp index 4645cd30b62..a7e95055b93 100644 --- a/src/map/utils/astarnodes.cpp +++ b/src/map/utils/astarnodes.cpp @@ -7,9 +7,11 @@ * Website: https://docs.opentibiabr.com/ */ -#include "astarnodes.hpp" -#include "creatures/monsters/monster.hpp" +#include "map/utils/astarnodes.hpp" + #include "creatures/combat/combat.hpp" +#include "creatures/monsters/monster.hpp" +#include "items/tile.hpp" AStarNodes::AStarNodes(uint32_t x, uint32_t y, int_fast32_t extraCost) : #if defined(__AVX2__) || defined(__SSE2__) @@ -69,7 +71,7 @@ bool AStarNodes::createOpenNode(AStarNode* parent, uint32_t x, uint32_t y, int_f return false; } - int32_t retNode = curNode++; + const int32_t retNode = curNode++; openNodes[retNode] = true; AStarNode &node = nodes[retNode]; @@ -112,7 +114,7 @@ AStarNode* AStarNodes::getBestNode() { best_node = (total_cost < best_node_f ? indices_array[i] : best_node); best_node_f = (total_cost < best_node_f ? total_cost : best_node_f); } - return (openNodes[best_node] ? &nodes[best_node] : NULL); + return (openNodes[best_node] ? &nodes[best_node] : nullptr); #elif defined(__AVX2__) const __m256i increment = _mm256_set1_epi32(8); __m256i indices = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); @@ -132,8 +134,8 @@ AStarNode* AStarNodes::getBestNode() { alignas(32) int32_t indices_array[8]; _mm256_store_si256(reinterpret_cast<__m256i*>(indices_array), minindices); - int32_t best_node = indices_array[(_mm_ctz(_mm256_movemask_epi8(_mm256_cmpeq_epi32(minvalues, res))) >> 2)]; - return (openNodes[best_node] ? &nodes[best_node] : NULL); + int32_t best_node = indices_array[(mm_ctz(_mm256_movemask_epi8(_mm256_cmpeq_epi32(minvalues, res))) >> 2)]; + return (openNodes[best_node] ? &nodes[best_node] : nullptr); #elif defined(__SSE4_1__) const __m128i increment = _mm_set1_epi32(4); __m128i indices = _mm_setr_epi32(0, 1, 2, 3); @@ -152,7 +154,7 @@ AStarNode* AStarNodes::getBestNode() { alignas(16) int32_t indices_array[4]; _mm_store_si128(reinterpret_cast<__m128i*>(indices_array), minindices); - int32_t best_node = indices_array[(_mm_ctz(_mm_movemask_epi8(_mm_cmpeq_epi32(minvalues, res))) >> 2)]; + int32_t best_node = indices_array[(mm_ctz(_mm_movemask_epi8(_mm_cmpeq_epi32(minvalues, res))) >> 2)]; return (openNodes[best_node] ? &nodes[best_node] : NULL); #elif defined(__SSE2__) auto _mm_sse2_min_epi32 = [](const __m128i a, const __m128i b) { @@ -182,8 +184,8 @@ AStarNode* AStarNodes::getBestNode() { alignas(16) int32_t indices_array[4]; _mm_store_si128(reinterpret_cast<__m128i*>(indices_array), minindices); - int32_t best_node = indices_array[(_mm_ctz(_mm_movemask_epi8(_mm_cmpeq_epi32(minvalues, res))) >> 2)]; - return (openNodes[best_node] ? &nodes[best_node] : NULL); + int32_t best_node = indices_array[(mm_ctz(_mm_movemask_epi8(_mm_cmpeq_epi32(minvalues, res))) >> 2)]; + return (openNodes[best_node] ? &nodes[best_node] : nullptr); #else int32_t best_node_f = std::numeric_limits<int32_t>::max(); int32_t best_node = -1; @@ -239,7 +241,7 @@ AStarNode* AStarNodes::getNodeByPosition(uint32_t x, uint32_t y) { v[3] = _mm_cmpeq_epi32(_mm_load_si128(reinterpret_cast<const __m128i*>(&nodesTable[pos + 12])), key); const uint32_t mask = _mm_movemask_epi8(_mm_packs_epi16(_mm_packs_epi32(v[0], v[1]), _mm_packs_epi32(v[2], v[3]))); if (mask != 0) { - return &nodes[pos + _mm_ctz(mask)]; + return &nodes[pos + mm_ctz(mask)]; } } curRound = curNode - 8; @@ -249,7 +251,7 @@ AStarNode* AStarNodes::getNodeByPosition(uint32_t x, uint32_t y) { v[1] = _mm_cmpeq_epi32(_mm_load_si128(reinterpret_cast<const __m128i*>(&nodesTable[pos + 4])), key); const uint32_t mask = _mm_movemask_epi8(_mm_packs_epi32(v[0], v[1])); if (mask != 0) { - return &nodes[pos + (_mm_ctz(mask) >> 1)]; + return &nodes[pos + (mm_ctz(mask) >> 1)]; } pos += 8; } @@ -269,7 +271,7 @@ AStarNode* AStarNodes::getNodeByPosition(uint32_t x, uint32_t y) { #endif } -int_fast32_t AStarNodes::getMapWalkCost(AStarNode* node, const Position &neighborPos) { +int_fast32_t AStarNodes::getMapWalkCost(const AStarNode* node, const Position &neighborPos) { // diagonal movement extra cost return (((std::abs(node->x - neighborPos.x) + std::abs(node->y - neighborPos.y)) - 1) * MAP_DIAGONALWALKCOST) + MAP_NORMALWALKCOST; } @@ -283,7 +285,7 @@ int_fast32_t AStarNodes::getTileWalkCost(const std::shared_ptr<Creature> &creatu cost += MAP_NORMALWALKCOST * 4; } if (const auto &field = tile->getFieldItem()) { - CombatType_t combatType = field->getCombatType(); + const CombatType_t combatType = field->getCombatType(); if (!creature->isImmune(combatType) && !creature->hasCondition(Combat::DamageToConditionType(combatType)) && (creature->getMonster() && !creature->getMonster()->canWalkOnFieldType(combatType))) { cost += MAP_NORMALWALKCOST * 18; } diff --git a/src/map/utils/astarnodes.hpp b/src/map/utils/astarnodes.hpp index d66171f0d53..6e4411855bb 100644 --- a/src/map/utils/astarnodes.hpp +++ b/src/map/utils/astarnodes.hpp @@ -30,7 +30,7 @@ class AStarNodes { int32_t getClosedNodes() const; AStarNode* getNodeByPosition(uint32_t x, uint32_t y); - static int_fast32_t getMapWalkCost(AStarNode* node, const Position &neighborPos); + static int_fast32_t getMapWalkCost(const AStarNode* node, const Position &neighborPos); static int_fast32_t getTileWalkCost(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &tile); private: @@ -40,8 +40,8 @@ class AStarNodes { static constexpr int32_t MAP_DIAGONALWALKCOST = 25; #if defined(__SSE2__) - alignas(16) uint32_t nodesTable[MAX_NODES]; - alignas(64) int32_t calculatedNodes[MAX_NODES]; + alignas(16) uint32_t nodesTable[MAX_NODES] {}; + alignas(64) int32_t calculatedNodes[MAX_NODES] {}; AStarNode nodes[MAX_NODES]; #else AStarNode nodes[MAX_NODES]; diff --git a/src/map/utils/mapsector.cpp b/src/map/utils/mapsector.cpp index 064ff837e8b..c6546ebd02c 100644 --- a/src/map/utils/mapsector.cpp +++ b/src/map/utils/mapsector.cpp @@ -7,8 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ +#include "map/utils/mapsector.hpp" + #include "creatures/creature.hpp" -#include "mapsector.hpp" bool MapSector::newSector = false; @@ -16,11 +17,15 @@ void MapSector::addCreature(const std::shared_ptr<Creature> &c) { creature_list.emplace_back(c); if (c->getPlayer()) { player_list.emplace_back(c); + } else if (c->getMonster()) { + monster_list.emplace_back(c); + } else if (c->getNpc()) { + npc_list.emplace_back(c); } } void MapSector::removeCreature(const std::shared_ptr<Creature> &c) { - auto iter = std::find(creature_list.begin(), creature_list.end(), c); + auto iter = std::ranges::find(creature_list, c); if (iter == creature_list.end()) { g_logger().error("[{}]: Creature not found in creature_list!", __FUNCTION__); return; @@ -31,7 +36,7 @@ void MapSector::removeCreature(const std::shared_ptr<Creature> &c) { creature_list.pop_back(); if (c->getPlayer()) { - iter = std::find(player_list.begin(), player_list.end(), c); + iter = std::ranges::find(player_list, c); if (iter == player_list.end()) { g_logger().error("[{}]: Player not found in player_list!", __FUNCTION__); return; @@ -40,5 +45,25 @@ void MapSector::removeCreature(const std::shared_ptr<Creature> &c) { assert(iter != player_list.end()); *iter = player_list.back(); player_list.pop_back(); + } else if (c->getMonster()) { + iter = std::ranges::find(monster_list, c); + if (iter == monster_list.end()) { + g_logger().error("[{}]: Monster not found in player_list!", __FUNCTION__); + return; + } + + assert(iter != monster_list.end()); + *iter = monster_list.back(); + monster_list.pop_back(); + } else if (c->getNpc()) { + iter = std::ranges::find(npc_list, c); + if (iter == npc_list.end()) { + g_logger().error("[{}]: NPC not found in player_list!", __FUNCTION__); + return; + } + + assert(iter != npc_list.end()); + *iter = npc_list.back(); + npc_list.pop_back(); } } diff --git a/src/map/utils/mapsector.hpp b/src/map/utils/mapsector.hpp index 7b95db7f78b..0b8be45e973 100644 --- a/src/map/utils/mapsector.hpp +++ b/src/map/utils/mapsector.hpp @@ -20,24 +20,27 @@ struct Floor { z(z) { } std::shared_ptr<Tile> getTile(uint16_t x, uint16_t y) const { - std::shared_lock sl(mutex); + std::shared_lock<std::shared_mutex> sl(mutex); return tiles[x & SECTOR_MASK][y & SECTOR_MASK].first; } void setTile(uint16_t x, uint16_t y, std::shared_ptr<Tile> tile) { - tiles[x & SECTOR_MASK][y & SECTOR_MASK].first = tile; + std::unique_lock<std::shared_mutex> ul(mutex); + tiles[x & SECTOR_MASK][y & SECTOR_MASK].first = std::move(tile); } std::shared_ptr<BasicTile> getTileCache(uint16_t x, uint16_t y) const { - std::shared_lock sl(mutex); + std::shared_lock<std::shared_mutex> sl(mutex); return tiles[x & SECTOR_MASK][y & SECTOR_MASK].second; } void setTileCache(uint16_t x, uint16_t y, const std::shared_ptr<BasicTile> &newTile) { + std::unique_lock<std::shared_mutex> ul(mutex); tiles[x & SECTOR_MASK][y & SECTOR_MASK].second = newTile; } const auto &getTiles() const { + std::shared_lock<std::shared_mutex> sl(mutex); return tiles; } @@ -45,13 +48,11 @@ struct Floor { return z; } - auto &getMutex() const { - return mutex; - } - private: std::pair<std::shared_ptr<Tile>, std::shared_ptr<BasicTile>> tiles[SECTOR_SIZE][SECTOR_SIZE] = {}; + mutable std::shared_mutex mutex; + uint8_t z { 0 }; }; @@ -59,32 +60,51 @@ class MapSector { public: MapSector() = default; - // non-copyable MapSector(const MapSector &) = delete; MapSector &operator=(const MapSector &) = delete; - - // non-moveable MapSector(const MapSector &&) = delete; MapSector &operator=(const MapSector &&) = delete; - const std::unique_ptr<Floor> &createFloor(uint32_t z) { - return floors[z] ? floors[z] : (floors[z] = std::make_unique<Floor>(z)); + std::shared_ptr<Floor> createFloor(uint32_t z) { + if (z >= MAP_MAX_LAYERS) { + g_logger().error("Attempt to create floor on invalid coordinate: {}", z); + return nullptr; + } + std::scoped_lock lock(floors_mutex); + if (!floors[z]) { + floors[z] = std::make_shared<Floor>(static_cast<uint8_t>(z)); + } + return floors[z]; } - const std::unique_ptr<Floor> &getFloor(uint8_t z) const { + std::shared_ptr<Floor> getFloor(uint8_t z) { + if (z >= MAP_MAX_LAYERS) { + g_logger().error("Attempt to get floor on invalid coordinate: {}", z); + return nullptr; + } + std::scoped_lock lock(floors_mutex); return floors[z]; } void addCreature(const std::shared_ptr<Creature> &c); + void removeCreature(const std::shared_ptr<Creature> &c); private: static bool newSector; + MapSector* sectorS = nullptr; MapSector* sectorE = nullptr; + std::vector<std::shared_ptr<Creature>> creature_list; std::vector<std::shared_ptr<Creature>> player_list; - std::unique_ptr<Floor> floors[MAP_MAX_LAYERS] = {}; + std::vector<std::shared_ptr<Creature>> monster_list; + std::vector<std::shared_ptr<Creature>> npc_list; + + mutable std::mutex floors_mutex; + + std::shared_ptr<Floor> floors[MAP_MAX_LAYERS] = {}; + uint32_t floorBits = 0; friend class Spectators; diff --git a/src/pch.hpp b/src/pch.hpp index b89830b9fdb..d66b5fc10ce 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -87,14 +87,10 @@ // FMT Custom Formatter for Enums template <typename E> -struct fmt::formatter<E, std::enable_if_t<std::is_enum_v<E>, char>> : fmt::formatter<std::underlying_type_t<E>> { - template <typename FormatContext> - auto format(E e, FormatContext &ctx) const { - return fmt::formatter<std::underlying_type_t<E>>::format( - static_cast<std::underlying_type_t<E>>(e), ctx - ); - } -}; +std::enable_if_t<std::is_enum_v<E>, std::underlying_type_t<E>> +format_as(E e) { + return static_cast<std::underlying_type_t<E>>(e); +} // GMP #include <gmp.h> @@ -174,17 +170,5 @@ struct fmt::formatter<E, std::enable_if_t<std::is_enum_v<E>, char>> : fmt::forma #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 +#include "account/account_info.hpp" +#include "config/config_enums.hpp" diff --git a/src/protobuf/appearances.proto b/src/protobuf/appearances.proto index ed924febfc4..1ca8defac0c 100644 --- a/src/protobuf/appearances.proto +++ b/src/protobuf/appearances.proto @@ -42,6 +42,7 @@ enum ITEM_CATEGORY { ITEM_CATEGORY_TIBIA_COINS = 23; ITEM_CATEGORY_CREATURE_PRODUCTS = 24; ITEM_CATEGORY_QUIVER = 25; + ITEM_CATEGORY_SOULCORES = 26; } enum PLAYER_PROFESSION { diff --git a/src/security/argon.cpp b/src/security/argon.cpp index 52fa4b0c94b..206c4ac0ab0 100644 --- a/src/security/argon.cpp +++ b/src/security/argon.cpp @@ -7,9 +7,10 @@ * Website: https://docs.opentibiabr.com/ */ +#include "security/argon.hpp" + #include "config/configmanager.hpp" #include "database/database.hpp" -#include "security/argon.hpp" #include <argon2.h> @@ -52,7 +53,6 @@ uint32_t Argon2::parseBitShift(const std::string &bitShiftStr) const { } bool Argon2::verifyPassword(const std::string &password, const std::string &phash) const { - const std::regex re("\\$([A-Za-z0-9+/]+)\\$([A-Za-z0-9+/]+)"); std::smatch match; if (!std::regex_search(phash, match, re)) { @@ -60,8 +60,8 @@ bool Argon2::verifyPassword(const std::string &password, const std::string &phas return false; } - std::vector<uint8_t> salt = base64_decode(match[1]); - std::vector<uint8_t> hash = base64_decode(match[2]); + const std::vector<uint8_t> salt = base64_decode(match[1]); + const std::vector<uint8_t> hash = base64_decode(match[2]); // Hash the password std::vector<uint8_t> computed_hash(hash.size()); @@ -74,17 +74,17 @@ bool Argon2::verifyPassword(const std::string &password, const std::string &phas return computed_hash == hash; } -std::vector<uint8_t> Argon2::base64_decode(const std::string &input) const { +std::vector<uint8_t> Argon2::base64_decode(const std::string &input) { const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::vector<uint8_t> ret; int i = 0; uint32_t val = 0; - for (char c : input) { + for (const char c : input) { if (isspace(c) || c == '=') { continue; } - size_t pos = base64_chars.find(c); + const size_t pos = base64_chars.find(c); if (pos == std::string::npos) { g_logger().warn("Invalid character in base64 string"); } else if (pos > std::numeric_limits<uint32_t>::max()) { @@ -94,9 +94,9 @@ std::vector<uint8_t> Argon2::base64_decode(const std::string &input) const { } if (++i % 4 == 0) { - ret.push_back((val >> 16) & 0xFF); - ret.push_back((val >> 8) & 0xFF); - ret.push_back(val & 0xFF); + ret.emplace_back((val >> 16) & 0xFF); + ret.emplace_back((val >> 8) & 0xFF); + ret.emplace_back(val & 0xFF); } } @@ -105,11 +105,11 @@ std::vector<uint8_t> Argon2::base64_decode(const std::string &input) const { g_logger().warn("Invalid length for base64 string"); break; case 2: - ret.push_back((val >> 4) & 0xFF); + ret.emplace_back((val >> 4) & 0xFF); break; case 3: - ret.push_back((val >> 10) & 0xFF); - ret.push_back((val >> 2) & 0xFF); + ret.emplace_back((val >> 10) & 0xFF); + ret.emplace_back((val >> 2) & 0xFF); break; default: g_logger().warn("Unexpected remainder when dividing string length by 4"); diff --git a/src/security/argon.hpp b/src/security/argon.hpp index ea09dcffccb..839ce02a484 100644 --- a/src/security/argon.hpp +++ b/src/security/argon.hpp @@ -25,12 +25,12 @@ class Argon2 { private: uint32_t parseBitShift(const std::string &bitShiftStr) const; bool verifyPassword(const std::string &password, const std::string &phash) const; - std::vector<uint8_t> base64_decode(const std::string &input) const; + static std::vector<uint8_t> base64_decode(const std::string &input); static const std::regex re; static const std::string base64_chars; std::string m_const_str; - uint32_t m_cost; - uint32_t t_cost; - uint32_t parallelism; + uint32_t m_cost {}; + uint32_t t_cost {}; + uint32_t parallelism {}; }; diff --git a/src/security/rsa.cpp b/src/security/rsa.cpp index 536ebdc02d3..18e1f6e8393 100644 --- a/src/security/rsa.cpp +++ b/src/security/rsa.cpp @@ -7,9 +7,10 @@ * Website: https://docs.opentibiabr.com/ */ -#include "lib/di/container.hpp" #include "security/rsa.hpp" +#include "lib/di/container.hpp" + RSA::RSA(Logger &logger) : logger(logger) { mpz_init(n); @@ -26,8 +27,8 @@ RSA &RSA::getInstance() { } void RSA::start() { - const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); - const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); + const auto p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); + const auto q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); try { if (!loadPEM("key.pem")) { // file doesn't exist - switch to base10-hardcoded keys @@ -108,13 +109,17 @@ std::string RSA::base64Decrypt(const std::string &input) const { auto posOfCharacter = [](const uint8_t chr) -> uint16_t { if (chr >= 'A' && chr <= 'Z') { return chr - 'A'; - } else if (chr >= 'a' && chr <= 'z') { + } + if (chr >= 'a' && chr <= 'z') { return chr - 'a' + ('Z' - 'A') + 1; - } else if (chr >= '0' && chr <= '9') { + } + if (chr >= '0' && chr <= '9') { return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2; - } else if (chr == '+' || chr == '-') { + } + if (chr == '+' || chr == '-') { return 62; - } else if (chr == '/' || chr == '_') { + } + if (chr == '/' || chr == '_') { return 63; } g_logger().error("[RSA::base64Decrypt] - Invalid base6409"); @@ -122,19 +127,19 @@ std::string RSA::base64Decrypt(const std::string &input) const { }; if (input.empty()) { - return std::string(); + return {}; } - size_t length = input.length(); + const size_t length = input.length(); size_t pos = 0; std::string output; output.reserve(length / 4 * 3); while (pos < length) { - uint16_t pos1 = posOfCharacter(input[pos + 1]); + const uint16_t pos1 = posOfCharacter(input[pos + 1]); output.push_back(static_cast<std::string::value_type>(((posOfCharacter(input[pos])) << 2) + ((pos1 & 0x30) >> 4))); if (input[pos + 2] != '=' && input[pos + 2] != '.') { - uint16_t pos2 = posOfCharacter(input[pos + 2]); + const uint16_t pos2 = posOfCharacter(input[pos + 2]); output.push_back(static_cast<std::string::value_type>(((pos1 & 0x0f) << 4) + ((pos2 & 0x3c) >> 2))); if (input[pos + 3] != '=' && input[pos + 3] != '.') { output.push_back(static_cast<std::string::value_type>(((pos2 & 0x03) << 6) + posOfCharacter(input[pos + 3]))); @@ -188,7 +193,7 @@ uint16_t RSA::decodeLength(char*&pos) const { void RSA::readHexString(char*&pos, uint16_t length, std::string &output) const { output.reserve(static_cast<size_t>(length) * 2); for (uint16_t i = 0; i < length; ++i) { - auto hex = static_cast<uint8_t>(*pos++); + const auto hex = static_cast<uint8_t>(*pos++); output.push_back("0123456789ABCDEF"[(hex >> 4) & 15]); output.push_back("0123456789ABCDEF"[hex & 15]); } diff --git a/src/security/rsa.hpp b/src/security/rsa.hpp index a6de23b4e13..a6575a5515f 100644 --- a/src/security/rsa.hpp +++ b/src/security/rsa.hpp @@ -13,7 +13,7 @@ class Logger; class RSA { public: - RSA(Logger &logger); + explicit RSA(Logger &logger); ~RSA(); // Singleton - ensures we don't accidentally copy it @@ -34,8 +34,8 @@ class RSA { private: Logger &logger; - mpz_t n; - mpz_t d; + mpz_t n {}; + mpz_t d {}; }; constexpr auto g_RSA = RSA::getInstance; diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp index 91f62a7602d..76c954af41c 100644 --- a/src/server/network/connection/connection.cpp +++ b/src/server/network/connection/connection.cpp @@ -16,12 +16,13 @@ #include "game/scheduling/dispatcher.hpp" #include "server/network/message/networkmessage.hpp" #include "server/server.hpp" +#include "utils/tools.hpp" ConnectionManager &ConnectionManager::getInstance() { return inject<ConnectionManager>(); } -Connection_ptr ConnectionManager::createConnection(asio::io_service &io_service, ConstServicePort_ptr servicePort) { +Connection_ptr ConnectionManager::createConnection(asio::io_service &io_service, const ConstServicePort_ptr &servicePort) { auto connection = std::make_shared<Connection>(io_service, servicePort); connections.emplace(connection); return connection; @@ -126,6 +127,7 @@ void Connection::acceptInternal(bool toggleParseHeader) { close(FORCE_CLOSE); } } + void Connection::parseProxyIdentification(const std::error_code &error) { std::scoped_lock lock(connectionLock); readTimer.cancel(); diff --git a/src/server/network/connection/connection.hpp b/src/server/network/connection/connection.hpp index 0666ef35d8d..139bfc73024 100644 --- a/src/server/network/connection/connection.hpp +++ b/src/server/network/connection/connection.hpp @@ -36,7 +36,7 @@ class ConnectionManager { static ConnectionManager &getInstance(); - Connection_ptr createConnection(asio::io_service &io_service, ConstServicePort_ptr servicePort); + Connection_ptr createConnection(asio::io_service &io_service, const ConstServicePort_ptr &servicePort); void releaseConnection(const Connection_ptr &connection); void closeAll(); diff --git a/src/server/network/message/networkmessage.cpp b/src/server/network/message/networkmessage.cpp index 5b7c8a143b9..0fb8b63324f 100644 --- a/src/server/network/message/networkmessage.cpp +++ b/src/server/network/message/networkmessage.cpp @@ -8,6 +8,7 @@ */ #include "server/network/message/networkmessage.hpp" + #include "items/containers/container.hpp" int32_t NetworkMessage::decodeHeader() { diff --git a/src/server/network/message/outputmessage.cpp b/src/server/network/message/outputmessage.cpp index db2322952d1..9c7a70ede45 100644 --- a/src/server/network/message/outputmessage.cpp +++ b/src/server/network/message/outputmessage.cpp @@ -7,7 +7,7 @@ * Website: https://docs.opentibiabr.com/ */ -#include "outputmessage.hpp" +#include "server/network/message/outputmessage.hpp" #include "lib/di/container.hpp" #include "server/network/protocol/protocol.hpp" @@ -53,7 +53,7 @@ void OutputMessagePool::addProtocolToAutosend(const Protocol_ptr &protocol) { void OutputMessagePool::removeProtocolFromAutosend(const Protocol_ptr &protocol) { // dispatcher thread - auto it = std::ranges::find(bufferedProtocols.begin(), bufferedProtocols.end(), protocol); + const auto it = std::ranges::find(bufferedProtocols, protocol); if (it != bufferedProtocols.end()) { *it = bufferedProtocols.back(); bufferedProtocols.pop_back(); diff --git a/src/server/network/protocol/protocol.cpp b/src/server/network/protocol/protocol.cpp index 129177d434b..bbb8291a328 100644 --- a/src/server/network/protocol/protocol.cpp +++ b/src/server/network/protocol/protocol.cpp @@ -14,6 +14,7 @@ #include "server/network/message/outputmessage.hpp" #include "security/rsa.hpp" #include "game/scheduling/dispatcher.hpp" +#include "utils/tools.hpp" #include <lib/logging/log_with_spd_log.hpp> @@ -52,8 +53,8 @@ bool Protocol::sendRecvMessageCallback(NetworkMessage &msg) { g_dispatcher().addEvent( [&msg, protocolWeak = std::weak_ptr<Protocol>(shared_from_this())]() { - if (auto protocol = protocolWeak.lock()) { - if (auto protocolConnection = protocol->getConnection()) { + if (const auto &protocol = protocolWeak.lock()) { + if (const auto &protocolConnection = protocol->getConnection()) { protocol->parsePacket(msg); protocolConnection->resumeWork(); } @@ -67,7 +68,7 @@ bool Protocol::sendRecvMessageCallback(NetworkMessage &msg) { bool Protocol::onRecvMessage(NetworkMessage &msg) { if (checksumMethod != CHECKSUM_METHOD_NONE) { - uint32_t recvChecksum = msg.get<uint32_t>(); + const auto recvChecksum = msg.get<uint32_t>(); if (checksumMethod == CHECKSUM_METHOD_SEQUENCE) { if (recvChecksum == 0) { // checksum 0 indicate that the packet should be connection ping - 0x1C packet header @@ -75,8 +76,7 @@ bool Protocol::onRecvMessage(NetworkMessage &msg) { return false; } - uint32_t checksum; - checksum = ++clientSequenceNumber; + const uint32_t checksum = ++clientSequenceNumber; if (clientSequenceNumber >= 0x7FFFFFFF) { clientSequenceNumber = 0; } @@ -87,7 +87,7 @@ bool Protocol::onRecvMessage(NetworkMessage &msg) { } } else { uint32_t checksum; - if (int32_t len = msg.getLength() - msg.getBufferPosition(); + if (const int32_t len = msg.getLength() - msg.getBufferPosition(); len > 0) { checksum = adlerChecksum(msg.getBuffer() + msg.getBufferPosition(), len); } else { @@ -226,7 +226,7 @@ bool Protocol::RSA_decrypt(NetworkMessage &msg) { return false; } - auto charData = static_cast<char*>(static_cast<void*>(msg.getBuffer())); + const auto charData = static_cast<char*>(static_cast<void*>(msg.getBuffer())); // Does not break strict aliasing g_RSA().decrypt(charData + msg.getBufferPosition()); return (msg.getByte() == 0); @@ -245,7 +245,7 @@ Connection_ptr Protocol::getConnection() const { } uint32_t Protocol::getIP() const { - if (auto protocolConnection = getConnection()) { + if (const auto protocolConnection = getConnection()) { return protocolConnection->getIP(); } @@ -257,7 +257,9 @@ bool Protocol::compression(OutputMessage &outputMessage) const { return false; } - static const thread_local auto &compress = std::make_unique<ZStream>(); + static thread_local auto compress_ptr = std::make_unique<ZStream>(); + static const auto &compress = compress_ptr; + if (!compress->stream) { return false; } diff --git a/src/server/network/protocol/protocol.hpp b/src/server/network/protocol/protocol.hpp index 7d0a9534dcf..2b139e79ee8 100644 --- a/src/server/network/protocol/protocol.hpp +++ b/src/server/network/protocol/protocol.hpp @@ -21,7 +21,7 @@ class NetworkMessage; class Protocol : public std::enable_shared_from_this<Protocol> { public: - explicit Protocol(Connection_ptr initConnection); + explicit Protocol(const Connection_ptr &initConnection); virtual ~Protocol() = default; @@ -61,6 +61,7 @@ class Protocol : public std::enable_shared_from_this<Protocol> { void setXTEAKey(const uint32_t* newKey) { std::ranges::copy(newKey, newKey + 4, this->key.begin()); } + void setChecksumMethod(ChecksumMethods_t method) { checksumMethod = method; } diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index ae67bad447f..2f7ff9e2479 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -7,42 +7,55 @@ * Website: https://docs.opentibiabr.com/ */ -#include "creatures/players/management/ban.hpp" +#include "server/network/protocol/protocolgame.hpp" + +#include "account/account.hpp" +#include "config/configmanager.hpp" #include "core.hpp" -#include "declarations.hpp" -#include "game/game.hpp" -#include "creatures/players/imbuements/imbuements.hpp" -#include "io/functions/iologindata_load_player.hpp" -#include "io/iobestiary.hpp" -#include "io/io_bosstiary.hpp" -#include "io/iologindata.hpp" -#include "io/iomarket.hpp" -#include "lua/modules/modules.hpp" +#include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/combat/condition.hpp" +#include "creatures/combat/spells.hpp" +#include "creatures/interactions/chat.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/monsters/monsters.hpp" -#include "game/modal_window/modal_window.hpp" -#include "server/network/message/outputmessage.hpp" -#include "creatures/players/player.hpp" -#include "creatures/players/wheel/player_wheel.hpp" +#include "creatures/npcs/npc.hpp" #include "creatures/players/achievement/player_achievement.hpp" #include "creatures/players/cyclopedia/player_badge.hpp" #include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "creatures/players/cyclopedia/player_title.hpp" #include "creatures/players/grouping/familiars.hpp" -#include "server/network/protocol/protocolgame.hpp" -#include "game/scheduling/dispatcher.hpp" -#include "creatures/combat/spells.hpp" -#include "utils/tools.hpp" +#include "creatures/players/grouping/party.hpp" +#include "creatures/players/grouping/team_finder.hpp" +#include "creatures/players/highscore_category.hpp" +#include "creatures/players/imbuements/imbuements.hpp" +#include "creatures/players/management/ban.hpp" #include "creatures/players/management/waitlist.hpp" +#include "creatures/players/player.hpp" +#include "creatures/players/vip/player_vip.hpp" +#include "creatures/players/wheel/player_wheel.hpp" +#include "enums/player_icons.hpp" +#include "game/game.hpp" +#include "game/modal_window/modal_window.hpp" +#include "game/scheduling/dispatcher.hpp" +#include "io/functions/iologindata_load_player.hpp" +#include "io/io_bosstiary.hpp" +#include "io/iobestiary.hpp" +#include "io/iologindata.hpp" +#include "io/iomarket.hpp" +#include "io/ioprey.hpp" +#include "items/items_classification.hpp" #include "items/weapons/weapons.hpp" -#include "enums/object_category.hpp" -#include "enums/account_type.hpp" -#include "enums/account_group_type.hpp" +#include "lua/creature/creatureevent.hpp" +#include "lua/modules/modules.hpp" +#include "server/network/message/outputmessage.hpp" +#include "utils/tools.hpp" +#include "creatures/players/vocations/vocation.hpp" + #include "enums/account_coins.hpp" +#include "enums/account_group_type.hpp" +#include "enums/account_type.hpp" +#include "enums/object_category.hpp" #include "enums/player_blessings.hpp" -#include "creatures/players/highscore_category.hpp" - /* * NOTE: This namespace is used so that we can add functions without having to declare them in the ".hpp/.hpp" file * Do not use functions only in the .cpp scope without having a namespace, it may conflict with functions in other files of the same name @@ -51,16 +64,6 @@ // This "getIteration" function will allow us to get the total number of iterations that run within a specific map // Very useful to send the total amount in certain bytes in the ProtocolGame class namespace { - template <typename T> - uint16_t getIterationIncreaseCount(T &map) { - uint16_t totalIterationCount = 0; - for ([[maybe_unused]] const auto &[first, second] : map) { - totalIterationCount++; - } - - return totalIterationCount; - } - template <typename T> uint16_t getVectorIterationIncreaseCount(T &vector) { uint16_t totalIterationCount = 0; @@ -71,7 +74,7 @@ namespace { return totalIterationCount; } - void addOutfitAndMountBytes(NetworkMessage &msg, std::shared_ptr<Item> item, const CustomAttribute* attribute, const std::string &head, const std::string &body, const std::string &legs, const std::string &feet, bool addAddon = false, bool addByte = false) { + void addOutfitAndMountBytes(NetworkMessage &msg, const std::shared_ptr<Item> &item, const CustomAttribute* attribute, const std::string &head, const std::string &body, const std::string &legs, const std::string &feet, bool addAddon = false, bool addByte = false) { auto look = attribute->getAttribute<uint16_t>(); msg.add<uint16_t>(look); if (look != 0) { @@ -116,7 +119,7 @@ namespace { * @param msg The network message to which the imbuement damage should be added. * @param player Pointer to the player for whom the imbuement damage should be handled. */ - void handleImbuementDamage(NetworkMessage &msg, std::shared_ptr<Player> player) { + void handleImbuementDamage(NetworkMessage &msg, const std::shared_ptr<Player> &player) { bool imbueDmg = false; std::shared_ptr<Item> weapon = player->getWeapon(); if (weapon) { @@ -154,7 +157,7 @@ namespace { * * @param[in] player The pointer to the player whose equipped items are considered. */ - void calculateAbsorbValues(std::shared_ptr<Player> player, NetworkMessage &msg, uint8_t &combats) { + void calculateAbsorbValues(const std::shared_ptr<Player> &player, NetworkMessage &msg, uint8_t &combats) { alignas(16) uint16_t damageModifiers[COMBAT_COUNT] = { 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000 }; for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { @@ -162,7 +165,7 @@ namespace { continue; } - std::shared_ptr<Item> item = player->getInventoryItem(static_cast<Slots_t>(slot)); + const auto item = player->getInventoryItem(static_cast<Slots_t>(slot)); if (!item) { continue; } @@ -245,12 +248,12 @@ namespace { } } // namespace -ProtocolGame::ProtocolGame(Connection_ptr initConnection) : +ProtocolGame::ProtocolGame(const Connection_ptr &initConnection) : Protocol(initConnection) { version = CLIENT_VERSION; } -void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier) { +void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier) const { const ItemType &it = Item::items[id]; msg.add<uint16_t>(it.id); @@ -309,7 +312,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint } } -void ProtocolGame::AddItem(NetworkMessage &msg, std::shared_ptr<Item> item) { +void ProtocolGame::AddItem(NetworkMessage &msg, const std::shared_ptr<Item> &item) { if (!item) { return; } @@ -347,7 +350,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, std::shared_ptr<Item> item) { if (container && containerType == 0 && container->getHoldingPlayer() == player) { uint32_t lootFlags = 0; uint32_t obtainFlags = 0; - for (auto [category, containerMap] : player->m_managedContainers) { + for (const auto &[category, containerMap] : player->m_managedContainers) { if (!isValidObjectCategory(category)) { continue; } @@ -370,7 +373,7 @@ void ProtocolGame::AddItem(NetworkMessage &msg, std::shared_ptr<Item> item) { // Quiver ammo count if (container && containerType == 0 && item->isQuiver() && player->getThing(CONST_SLOT_RIGHT) == item) { uint16_t ammoTotal = 0; - for (std::shared_ptr<Item> listItem : container->getItemList()) { + for (const std::shared_ptr<Item> &listItem : container->getItemList()) { if (player->getLevel() >= Item::items[listItem->getID()].minReqLevel) { ammoTotal += listItem->getItemCount(); } @@ -705,7 +708,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { return; } - OperatingSystem_t operatingSystem = static_cast<OperatingSystem_t>(msg.get<uint16_t>()); + auto operatingSystem = static_cast<OperatingSystem_t>(msg.get<uint16_t>()); version = msg.get<uint16_t>(); // Protocol version g_logger().trace("Protocol version: {}", version); @@ -754,7 +757,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { std::ostringstream ss; std::string sessionKey = msg.getString(); std::string accountDescriptor = sessionKey; - std::string password = ""; + std::string password; if (authType != "session") { size_t pos = sessionKey.find('\n'); @@ -791,7 +794,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { foundPlayer->client->disconnectClient("You are already connected through another client. Please use only one client at a time!"); } - uint32_t timeStamp = msg.get<uint32_t>(); + auto timeStamp = msg.get<uint32_t>(); uint8_t randNumber = msg.getByte(); if (challengeTimestamp != timeStamp || challengeRandom != randNumber) { disconnect(); @@ -799,7 +802,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { } // OTCv8 version detection - uint16_t otcV8StringLength = msg.get<uint16_t>(); + auto otcV8StringLength = msg.get<uint16_t>(); if (otcV8StringLength == 5 && msg.getString(5) == "OTCv8") { otclientV8 = msg.get<uint16_t>(); // 253, 260, 261, ... } @@ -885,7 +888,7 @@ void ProtocolGame::onConnect() { // To support 11.10-, not have problems with 11.11+ output->add<uint32_t>(adlerChecksum(output->getOutputBuffer() + sizeof(uint32_t), 8)); - send(std::move(output)); + send(output); } void ProtocolGame::disconnectClient(const std::string &message) const { @@ -941,7 +944,6 @@ void ProtocolGame::parsePacketDead(uint8_t recvbyte) { g_game().removePlayerUniqueLogin(player->getName()); } disconnect(); - IOLoginData::updateOnlineStatus(player->getGUID(), false); return; } @@ -1001,24 +1003,24 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvby case 0x1E: g_game().playerReceivePing(player->getID()); break; - case 0x2a: + case 0x28: + parseStashWithdraw(msg); + break; + case 0x29: + parseRetrieveDepotSearch(msg); + break; + case 0x2A: parseCyclopediaMonsterTracker(msg); break; case 0x2B: parsePartyAnalyzerAction(msg); break; - case 0x2c: + case 0x2C: parseLeaderFinderWindow(msg); break; - case 0x2d: + case 0x2D: parseMemberFinderWindow(msg); break; - case 0x28: - parseStashWithdraw(msg); - break; - case 0x29: - parseRetrieveDepotSearch(msg); - break; case 0x32: parseExtendedOpcode(msg); break; // otclient extended opcode @@ -1263,6 +1265,9 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvby case 0xCD: parseInspectionObject(msg); break; + case 0xCF: + sendBlessingWindow(); + break; case 0xD2: g_game().playerRequestOutfit(player->getID()); break; @@ -1378,12 +1383,12 @@ void ProtocolGame::parseHotkeyEquip(NetworkMessage &msg) { return; } - uint16_t itemId = msg.get<uint16_t>(); - uint8_t tier = msg.get<uint8_t>(); + auto itemId = msg.get<uint16_t>(); + auto tier = msg.get<uint8_t>(); g_game().playerEquipItem(player->getID(), itemId, Item::items[itemId].upgradeClassification > 0, tier); } -void ProtocolGame::GetTileDescription(std::shared_ptr<Tile> tile, NetworkMessage &msg) { +void ProtocolGame::GetTileDescription(const std::shared_ptr<Tile> &tile, NetworkMessage &msg) { if (oldProtocol) { msg.add<uint16_t>(0x00); // Env effects } @@ -1414,8 +1419,7 @@ void ProtocolGame::GetTileDescription(std::shared_ptr<Tile> tile, NetworkMessage const CreatureVector* creatures = tile->getCreatures(); if (creatures) { bool playerAdded = false; - for (auto it = creatures->rbegin(); it != creatures->rend(); ++it) { - std::shared_ptr<Creature> creature = *it; + for (auto creature : std::ranges::reverse_view(*creatures)) { if (!player->canSeeCreature(creature)) { continue; } @@ -1511,9 +1515,9 @@ void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool &known, uint32_t &remo continue; } // We need to protect party players from removing - std::shared_ptr<Creature> creature = g_game().getCreatureByID(*it); - if (std::shared_ptr<Player> checkPlayer; - creature && (checkPlayer = creature->getPlayer()) != nullptr) { + const auto &creature = g_game().getCreatureByID(*it); + const auto &checkPlayer = creature ? creature->getPlayer() : nullptr; + if (checkPlayer) { if (player->getParty() != checkPlayer->getParty() && !canSee(creature)) { removedKnown = *it; knownCreatureSet.erase(it); @@ -1539,7 +1543,7 @@ void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool &known, uint32_t &remo } } -bool ProtocolGame::canSee(std::shared_ptr<Creature> c) const { +bool ProtocolGame::canSee(const std::shared_ptr<Creature> &c) const { if (!c || !player || c->isRemoved()) { return false; } @@ -1592,12 +1596,12 @@ void ProtocolGame::parseChannelExclude(NetworkMessage &msg) { } void ProtocolGame::parseOpenChannel(NetworkMessage &msg) { - uint16_t channelId = msg.get<uint16_t>(); + auto channelId = msg.get<uint16_t>(); g_game().playerOpenChannel(player->getID(), channelId); } void ProtocolGame::parseCloseChannel(NetworkMessage &msg) { - uint16_t channelId = msg.get<uint16_t>(); + auto channelId = msg.get<uint16_t>(); g_game().playerCloseChannel(player->getID(), channelId); } @@ -1659,7 +1663,7 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { } uint16_t startBufferPosition = msg.getBufferPosition(); - Module* outfitModule = g_modules().getEventByRecvbyte(0xD3, false); + const auto &outfitModule = g_modules().getEventByRecvbyte(0xD3, false); if (outfitModule) { outfitModule->executeOnRecvbyte(player, msg); } @@ -1694,7 +1698,7 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { msg.get<uint32_t>(); } else if (outfitType == 2) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); newOutfit.lookMount = msg.get<uint16_t>(); newOutfit.lookMountHead = std::min<uint8_t>(132, msg.getByte()); @@ -1715,7 +1719,7 @@ void ProtocolGame::parseToggleMount(NetworkMessage &msg) { void ProtocolGame::parseApplyImbuement(NetworkMessage &msg) { uint8_t slot = msg.getByte(); - uint32_t imbuementId = msg.get<uint32_t>(); + auto imbuementId = msg.get<uint32_t>(); bool protectionCharm = msg.getByte() != 0x00; g_game().playerApplyImbuement(player->getID(), imbuementId, slot, protectionCharm); } @@ -1731,7 +1735,7 @@ void ProtocolGame::parseCloseImbuementWindow(NetworkMessage &) { void ProtocolGame::parseUseItem(NetworkMessage &msg) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); uint8_t index = msg.getByte(); g_game().playerUseItem(player->getID(), pos, stackpos, index, itemId); @@ -1739,19 +1743,19 @@ void ProtocolGame::parseUseItem(NetworkMessage &msg) { void ProtocolGame::parseUseItemEx(NetworkMessage &msg) { Position fromPos = msg.getPosition(); - uint16_t fromItemId = msg.get<uint16_t>(); + auto fromItemId = msg.get<uint16_t>(); uint8_t fromStackPos = msg.getByte(); Position toPos = msg.getPosition(); - uint16_t toItemId = msg.get<uint16_t>(); + auto toItemId = msg.get<uint16_t>(); uint8_t toStackPos = msg.getByte(); g_game().playerUseItemEx(player->getID(), fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId); } void ProtocolGame::parseUseWithCreature(NetworkMessage &msg) { Position fromPos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t fromStackPos = msg.getByte(); - uint32_t creatureId = msg.get<uint32_t>(); + auto creatureId = msg.get<uint32_t>(); g_game().playerUseWithCreature(player->getID(), fromPos, fromStackPos, creatureId, itemId); } @@ -1777,7 +1781,7 @@ void ProtocolGame::parseTeleport(NetworkMessage &msg) { void ProtocolGame::parseThrow(NetworkMessage &msg) { Position fromPos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t fromStackpos = msg.getByte(); Position toPos = msg.getPosition(); uint8_t count = msg.getByte(); @@ -1789,13 +1793,13 @@ void ProtocolGame::parseThrow(NetworkMessage &msg) { void ProtocolGame::parseLookAt(NetworkMessage &msg) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerLookAt(player->getID(), itemId, pos, stackpos); } void ProtocolGame::parseLookInBattleList(NetworkMessage &msg) { - uint32_t creatureId = msg.get<uint32_t>(); + auto creatureId = msg.get<uint32_t>(); g_game().playerLookInBattleList(player->getID(), creatureId); } @@ -1806,7 +1810,7 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) { uint8_t variant = msg.getByte(); const Position pos = msg.getPosition(); - uint16_t itemId = 0; + auto itemId = 0; uint8_t stackpos = 0; bool lootAllCorpses = true; bool autoLoot = true; @@ -1820,7 +1824,6 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) { autoLoot = false; } g_logger().debug("[{}] variant {}, pos {}, itemId {}, stackPos {}", __FUNCTION__, variant, pos.toString(), itemId, stackpos); - g_game().playerQuickLoot(player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot); } @@ -1831,32 +1834,32 @@ void ProtocolGame::parseLootContainer(NetworkMessage &msg) { uint8_t action = msg.getByte(); if (action == 0) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, true); } else if (action == 1) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); g_game().playerClearManagedContainer(player->getID(), category, true); } else if (action == 2) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); g_game().playerOpenManagedContainer(player->getID(), category, true); } else if (action == 3) { bool useMainAsFallback = msg.getByte() == 1; g_game().playerSetQuickLootFallback(player->getID(), useMainAsFallback); } else if (action == 4) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_logger().debug("[{}] action {}, category {}, pos {}, itemId {}, stackPos {}", __FUNCTION__, action, static_cast<uint8_t>(category), pos.toString(), itemId, stackpos); g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, false); } else if (action == 5) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); g_game().playerClearManagedContainer(player->getID(), category, false); } else if (action == 6) { - ObjectCategory_t category = (ObjectCategory_t)msg.getByte(); + auto category = static_cast<ObjectCategory_t>(msg.getByte()); g_game().playerOpenManagedContainer(player->getID(), category, false); } @@ -1868,10 +1871,10 @@ void ProtocolGame::parseQuickLootBlackWhitelist(NetworkMessage &msg) { return; } - QuickLootFilter_t filter = (QuickLootFilter_t)msg.getByte(); + auto filter = (QuickLootFilter_t)msg.getByte(); std::vector<uint16_t> listedItems; - uint16_t size = msg.get<uint16_t>(); + auto size = msg.get<uint16_t>(); listedItems.reserve(size); for (int i = 0; i < size; i++) { @@ -1885,7 +1888,7 @@ void ProtocolGame::parseSay(NetworkMessage &msg) { std::string receiver; uint16_t channelId {}; - SpeakClasses type = static_cast<SpeakClasses>(msg.getByte()); + auto type = static_cast<SpeakClasses>(msg.getByte()); switch (type) { case TALKTYPE_PRIVATE_TO: case TALKTYPE_PRIVATE_RED_TO: @@ -1930,38 +1933,38 @@ void ProtocolGame::parseFightModes(NetworkMessage &msg) { } void ProtocolGame::parseAttack(NetworkMessage &msg) { - uint32_t creatureId = msg.get<uint32_t>(); + auto creatureId = msg.get<uint32_t>(); // msg.get<uint32_t>(); creatureId (same as above) g_game().playerSetAttackedCreature(player->getID(), creatureId); } void ProtocolGame::parseFollow(NetworkMessage &msg) { - uint32_t creatureId = msg.get<uint32_t>(); + auto creatureId = msg.get<uint32_t>(); // msg.get<uint32_t>(); creatureId (same as above) g_game().playerFollowCreature(player->getID(), creatureId); } void ProtocolGame::parseTextWindow(NetworkMessage &msg) { - uint32_t windowTextId = msg.get<uint32_t>(); + auto windowTextId = msg.get<uint32_t>(); const std::string newText = msg.getString(); g_game().playerWriteItem(player->getID(), windowTextId, newText); } void ProtocolGame::parseHouseWindow(NetworkMessage &msg) { uint8_t doorId = msg.getByte(); - uint32_t id = msg.get<uint32_t>(); + auto id = msg.get<uint32_t>(); const std::string text = msg.getString(); g_game().playerUpdateHouseWindow(player->getID(), doorId, id, text); } void ProtocolGame::parseLookInShop(NetworkMessage &msg) { - uint16_t id = msg.get<uint16_t>(); + auto id = msg.get<uint16_t>(); uint8_t count = msg.getByte(); g_game().playerLookInShop(player->getID(), id, count); } void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) { - uint16_t id = msg.get<uint16_t>(); + auto id = msg.get<uint16_t>(); uint8_t count = msg.getByte(); uint16_t amount = oldProtocol ? static_cast<uint16_t>(msg.getByte()) : msg.get<uint16_t>(); bool ignoreCap = msg.getByte() != 0; @@ -1970,7 +1973,7 @@ void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) { } void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) { - uint16_t id = msg.get<uint16_t>(); + auto id = msg.get<uint16_t>(); uint8_t count = std::max(msg.getByte(), (uint8_t)1); uint16_t amount = oldProtocol ? static_cast<uint16_t>(msg.getByte()) : msg.get<uint16_t>(); bool ignoreEquipped = msg.getByte() != 0; @@ -1980,9 +1983,9 @@ void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) { void ProtocolGame::parseRequestTrade(NetworkMessage &msg) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); - uint32_t playerId = msg.get<uint32_t>(); + auto playerId = msg.get<uint32_t>(); g_game().playerRequestTrade(player->getID(), pos, stackpos, playerId, itemId); } @@ -1998,13 +2001,13 @@ void ProtocolGame::parseAddVip(NetworkMessage &msg) { } void ProtocolGame::parseRemoveVip(NetworkMessage &msg) { - uint32_t guid = msg.get<uint32_t>(); + auto guid = msg.get<uint32_t>(); g_game().playerRequestRemoveVip(player->getID(), guid); } void ProtocolGame::parseEditVip(NetworkMessage &msg) { std::vector<uint8_t> vipGroupsId; - uint32_t guid = msg.get<uint32_t>(); + auto guid = msg.get<uint32_t>(); const std::string description = msg.getString(); uint32_t icon = std::min<uint32_t>(10, msg.get<uint32_t>()); // 10 is max icon in 9.63 bool notify = msg.getByte() != 0; @@ -2044,7 +2047,7 @@ void ProtocolGame::parseVipGroupActions(NetworkMessage &msg) { void ProtocolGame::parseRotateItem(NetworkMessage &msg) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); const auto &itemType = Item::items[itemId]; if (itemType.isPodium) { @@ -2056,7 +2059,7 @@ void ProtocolGame::parseRotateItem(NetworkMessage &msg) { void ProtocolGame::parseWrapableItem(NetworkMessage &msg) { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerWrapableItem(player->getID(), pos, stackpos, itemId); } @@ -2071,7 +2074,7 @@ void ProtocolGame::parseInspectionObject(NetworkMessage &msg) { Position pos = msg.getPosition(); g_game().playerInspectItem(player, pos); } else if (inspectionType == INSPECT_NPCTRADE || inspectionType == INSPECT_CYCLOPEDIA) { - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint16_t itemCount = msg.getByte(); g_game().playerInspectItem(player, itemId, static_cast<int8_t>(itemCount), (inspectionType == INSPECT_CYCLOPEDIA)); } @@ -2087,7 +2090,7 @@ void ProtocolGame::sendSessionEndInformation(SessionEndInformations information) disconnect(); } -void ProtocolGame::sendItemInspection(uint16_t itemId, uint8_t itemCount, std::shared_ptr<Item> item, bool cyclopedia) { +void ProtocolGame::sendItemInspection(uint16_t itemId, uint8_t itemCount, const std::shared_ptr<Item> &item, bool cyclopedia) { if (oldProtocol) { return; } @@ -2152,9 +2155,9 @@ void ProtocolGame::parseHighscores(NetworkMessage &msg) { return; } - HighscoreType_t type = static_cast<HighscoreType_t>(msg.getByte()); + auto type = static_cast<HighscoreType_t>(msg.getByte()); uint8_t category = msg.getByte(); - uint32_t vocation = msg.get<uint32_t>(); + auto vocation = msg.get<uint32_t>(); uint16_t page = 1; const std::string worldName = msg.getString(); msg.getByte(); // Game World Category @@ -2174,7 +2177,7 @@ void ProtocolGame::parseTaskHuntingAction(NetworkMessage &msg) { uint8_t slot = msg.getByte(); uint8_t action = msg.getByte(); bool upgrade = msg.getByte() != 0; - uint16_t raceId = msg.get<uint16_t>(); + auto raceId = msg.get<uint16_t>(); if (!g_configManager().getBoolean(TASK_HUNTING_ENABLED)) { return; @@ -2277,7 +2280,7 @@ void ProtocolGame::parseConfigureShowOffSocket(NetworkMessage &msg) { } Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerConfigureShowOffSocket(player->getID(), pos, stackpos, itemId); } @@ -2304,11 +2307,11 @@ void ProtocolGame::parseBestiarysendRaces() { } NetworkMessage msg; - msg.addByte(0xd5); + msg.addByte(0xD5); msg.add<uint16_t>(BESTY_RACE_LAST); std::map<uint16_t, std::string> mtype_list = g_game().getBestiaryList(); for (uint8_t i = BESTY_RACE_FIRST; i <= BESTY_RACE_LAST; i++) { - std::string BestClass = ""; + std::string BestClass; uint16_t count = 0; for (const auto &rit : mtype_list) { const auto mtype = g_monsters().getMonsterType(rit.second); @@ -2336,7 +2339,7 @@ void ProtocolGame::sendBestiaryEntryChanged(uint16_t raceid) { } NetworkMessage msg; - msg.addByte(0xd9); + msg.addByte(0xD9); msg.add<uint16_t>(raceid); writeToOutputBuffer(msg); } @@ -2346,8 +2349,8 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { return; } - uint16_t raceId = msg.get<uint16_t>(); - std::string Class = ""; + auto raceId = msg.get<uint16_t>(); + std::string Class; std::shared_ptr<MonsterType> mtype = nullptr; std::map<uint16_t, std::string> mtype_list = g_game().getBestiaryList(); @@ -2370,7 +2373,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { uint8_t currentLevel = g_iobestiary().getKillStatus(mtype, killCounter); NetworkMessage newmsg; - newmsg.addByte(0xd7); + newmsg.addByte(0xD7); newmsg.add<uint16_t>(raceId); newmsg.addString(Class); @@ -2432,7 +2435,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { } newmsg.addByte(attackmode); - newmsg.addByte(0x2); + newmsg.addByte(0x02); newmsg.add<uint32_t>(mtype->info.healthMax); newmsg.add<uint32_t>(mtype->info.experience); newmsg.add<uint16_t>(mtype->getBaseSpeed()); @@ -2444,9 +2447,9 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { std::map<uint8_t, int16_t> elements = g_iobestiary().getMonsterElements(mtype); newmsg.addByte(elements.size()); - for (auto it = std::begin(elements), end = std::end(elements); it != end; it++) { - newmsg.addByte(it->first); - newmsg.add<uint16_t>(it->second); + for (auto &element : elements) { + newmsg.addByte(element.first); + newmsg.add<uint16_t>(element.second); } newmsg.add<uint16_t>(1); @@ -2469,7 +2472,7 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { } void ProtocolGame::parseCyclopediaMonsterTracker(NetworkMessage &msg) { - uint16_t monsterRaceId = msg.get<uint16_t>(); + auto monsterRaceId = msg.get<uint16_t>(); // Bosstiary tracker: 0 = disabled, 1 = enabled // Bestiary tracker: 1 = enabled auto trackerButtonType = msg.getByte(); @@ -2724,16 +2727,16 @@ void ProtocolGame::parsePartyAnalyzerAction(NetworkMessage &msg) const { return; } - PartyAnalyzerAction_t action = static_cast<PartyAnalyzerAction_t>(msg.getByte()); + auto action = static_cast<PartyAnalyzerAction_t>(msg.getByte()); if (action == PARTYANALYZERACTION_RESET) { party->resetAnalyzer(); } else if (action == PARTYANALYZERACTION_PRICETYPE) { party->switchAnalyzerPriceType(); } else if (action == PARTYANALYZERACTION_PRICEVALUE) { - uint16_t size = msg.get<uint16_t>(); + auto size = msg.get<uint16_t>(); for (uint16_t i = 1; i <= size; i++) { - uint16_t itemId = msg.get<uint16_t>(); - uint64_t price = msg.get<uint64_t>(); + auto itemId = msg.get<uint16_t>(); + auto price = msg.get<uint64_t>(); player->setItemCustomPrice(itemId, price); } party->reloadPrices(); @@ -2757,7 +2760,7 @@ void ProtocolGame::parseLeaderFinderWindow(NetworkMessage &msg) { break; } case 2: { - uint32_t memberID = msg.get<uint32_t>(); + auto memberID = msg.get<uint32_t>(); std::shared_ptr<Player> member = g_game().getPlayerByGUID(memberID); if (!member) { return; @@ -2815,7 +2818,7 @@ void ProtocolGame::parseMemberFinderWindow(NetworkMessage &msg) { if (action == 0) { player->sendTeamFinderList(); } else { - uint32_t leaderID = msg.get<uint32_t>(); + auto leaderID = msg.get<uint32_t>(); std::shared_ptr<Player> leader = g_game().getPlayerByGUID(leaderID); if (!leader) { return; @@ -2846,9 +2849,9 @@ void ProtocolGame::parseSendBuyCharmRune(NetworkMessage &msg) { return; } - charmRune_t runeID = static_cast<charmRune_t>(msg.getByte()); + auto runeID = static_cast<charmRune_t>(msg.getByte()); uint8_t action = msg.getByte(); - uint16_t raceid = msg.get<uint16_t>(); + auto raceid = msg.get<uint16_t>(); g_iobestiary().sendBuyCharmRune(player, runeID, action, raceid); } @@ -2904,7 +2907,7 @@ void ProtocolGame::BestiarysendCharms() { removeRuneCost = (removeRuneCost * 75) / 100; } NetworkMessage msg; - msg.addByte(0xd8); + msg.addByte(0xD8); msg.add<uint32_t>(player->getCharmPoints()); const auto charmList = g_game().getCharmList(); @@ -2955,14 +2958,14 @@ void ProtocolGame::parseBestiarysendCreatures(NetworkMessage &msg) { std::ostringstream ss; std::map<uint16_t, std::string> race = {}; - std::string text = ""; + std::string text; uint8_t search = msg.getByte(); if (search == 1) { - uint16_t monsterAmount = msg.get<uint16_t>(); + auto monsterAmount = msg.get<uint16_t>(); std::map<uint16_t, std::string> mtype_list = g_game().getBestiaryList(); for (uint16_t monsterCount = 1; monsterCount <= monsterAmount; monsterCount++) { - uint16_t raceid = msg.get<uint16_t>(); + auto raceid = msg.get<uint16_t>(); if (player->getBestiaryKillCount(raceid) > 0) { auto it = mtype_list.find(raceid); if (it != mtype_list.end()) { @@ -2983,7 +2986,7 @@ void ProtocolGame::parseBestiarysendCreatures(NetworkMessage &msg) { text = raceName; } NetworkMessage newmsg; - newmsg.addByte(0xd6); + newmsg.addByte(0xD6); newmsg.addString(text); newmsg.add<uint16_t>(race.size()); std::map<uint16_t, uint32_t> creaturesKilled = g_iobestiary().getBestiaryKillCountByMonsterIDs(player, race); @@ -3033,7 +3036,7 @@ void ProtocolGame::parseBugReport(NetworkMessage &msg) { } void ProtocolGame::parseGreet(NetworkMessage &msg) { - uint32_t npcId = msg.get<uint32_t>(); + auto npcId = msg.get<uint32_t>(); g_game().playerNpcGreet(player->getID(), npcId); } @@ -3078,22 +3081,22 @@ void ProtocolGame::parseSendResourceBalance() { } void ProtocolGame::parseInviteToParty(NetworkMessage &msg) { - uint32_t targetId = msg.get<uint32_t>(); + auto targetId = msg.get<uint32_t>(); g_game().playerInviteToParty(player->getID(), targetId); } void ProtocolGame::parseJoinParty(NetworkMessage &msg) { - uint32_t targetId = msg.get<uint32_t>(); + auto targetId = msg.get<uint32_t>(); g_game().playerJoinParty(player->getID(), targetId); } void ProtocolGame::parseRevokePartyInvite(NetworkMessage &msg) { - uint32_t targetId = msg.get<uint32_t>(); + auto targetId = msg.get<uint32_t>(); g_game().playerRevokePartyInvitation(player->getID(), targetId); } void ProtocolGame::parsePassPartyLeadership(NetworkMessage &msg) { - uint32_t targetId = msg.get<uint32_t>(); + auto targetId = msg.get<uint32_t>(); g_game().playerPassPartyLeadership(player->getID(), targetId); } @@ -3103,7 +3106,7 @@ void ProtocolGame::parseEnableSharedPartyExperience(NetworkMessage &msg) { } void ProtocolGame::parseQuestLine(NetworkMessage &msg) { - uint16_t questId = msg.get<uint16_t>(); + auto questId = msg.get<uint16_t>(); g_game().playerShowQuestLine(player->getID(), questId); } @@ -3119,8 +3122,8 @@ void ProtocolGame::parseMarketBrowse(NetworkMessage &msg) { } else if ((oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY_OLD) || (!oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY)) { g_game().playerBrowseMarketOwnHistory(player->getID()); } else if (!oldProtocol) { - uint16_t itemId = msg.get<uint16_t>(); - uint8_t tier = msg.get<uint8_t>(); + auto itemId = msg.get<uint16_t>(); + auto tier = msg.get<uint8_t>(); player->sendMarketEnter(player->getLastDepotId()); g_game().playerBrowseMarket(player->getID(), itemId, tier); } else { @@ -3130,13 +3133,13 @@ void ProtocolGame::parseMarketBrowse(NetworkMessage &msg) { void ProtocolGame::parseMarketCreateOffer(NetworkMessage &msg) { uint8_t type = msg.getByte(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t itemTier = 0; if (!oldProtocol && Item::items[itemId].upgradeClassification > 0) { itemTier = msg.getByte(); } - uint16_t amount = msg.get<uint16_t>(); + auto amount = msg.get<uint16_t>(); uint64_t price = oldProtocol ? static_cast<uint64_t>(msg.get<uint32_t>()) : msg.get<uint64_t>(); bool anonymous = (msg.getByte() != 0); if (amount > 0 && price > 0) { @@ -3145,8 +3148,8 @@ void ProtocolGame::parseMarketCreateOffer(NetworkMessage &msg) { } void ProtocolGame::parseMarketCancelOffer(NetworkMessage &msg) { - uint32_t timestamp = msg.get<uint32_t>(); - uint16_t counter = msg.get<uint16_t>(); + auto timestamp = msg.get<uint32_t>(); + auto counter = msg.get<uint16_t>(); if (counter > 0) { g_game().playerCancelMarketOffer(player->getID(), timestamp, counter); } @@ -3155,9 +3158,9 @@ void ProtocolGame::parseMarketCancelOffer(NetworkMessage &msg) { } void ProtocolGame::parseMarketAcceptOffer(NetworkMessage &msg) { - uint32_t timestamp = msg.get<uint32_t>(); - uint16_t counter = msg.get<uint16_t>(); - uint16_t amount = msg.get<uint16_t>(); + auto timestamp = msg.get<uint32_t>(); + auto counter = msg.get<uint16_t>(); + auto amount = msg.get<uint16_t>(); if (amount > 0 && counter > 0) { g_game().playerAcceptMarketOffer(player->getID(), timestamp, counter, amount); } @@ -3166,7 +3169,7 @@ void ProtocolGame::parseMarketAcceptOffer(NetworkMessage &msg) { } void ProtocolGame::parseModalWindowAnswer(NetworkMessage &msg) { - uint32_t id = msg.get<uint32_t>(); + auto id = msg.get<uint32_t>(); uint8_t button = msg.getByte(); uint8_t choice = msg.getByte(); g_game().playerAnswerModalWindow(player->getID(), id, button, choice); @@ -3194,7 +3197,7 @@ void ProtocolGame::parseBrowseField(NetworkMessage &msg) { void ProtocolGame::parseSeekInContainer(NetworkMessage &msg) { uint8_t containerId = msg.getByte(); - uint16_t index = msg.get<uint16_t>(); + auto index = msg.get<uint16_t>(); auto primaryType = msg.getByte(); g_game().playerSeekInContainer(player->getID(), containerId, index, primaryType); } @@ -3228,7 +3231,7 @@ void ProtocolGame::sendChannelEvent(uint16_t channelId, const std::string &playe writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit) { +void ProtocolGame::sendCreatureOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit) { if (!canSee(creature)) { return; } @@ -3253,7 +3256,7 @@ void ProtocolGame::sendCreatureOutfit(std::shared_ptr<Creature> creature, const writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureLight(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureLight(const std::shared_ptr<Creature> &creature) { if (!canSee(creature)) { return; } @@ -3263,7 +3266,7 @@ void ProtocolGame::sendCreatureLight(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::addCreatureIcon(NetworkMessage &msg, std::shared_ptr<Creature> creature) { +void ProtocolGame::addCreatureIcon(NetworkMessage &msg, const std::shared_ptr<Creature> &creature) { if (!creature || !player || oldProtocol) { return; } @@ -3280,7 +3283,7 @@ void ProtocolGame::addCreatureIcon(NetworkMessage &msg, std::shared_ptr<Creature } } -void ProtocolGame::sendCreatureIcon(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureIcon(const std::shared_ptr<Creature> &creature) { if (!creature || !player || oldProtocol) { return; } @@ -3312,7 +3315,7 @@ void ProtocolGame::sendTibiaTime(int32_t time) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureWalkthrough(std::shared_ptr<Creature> creature, bool walkthrough) { +void ProtocolGame::sendCreatureWalkthrough(const std::shared_ptr<Creature> &creature, bool walkthrough) { if (!canSee(creature)) { return; } @@ -3324,7 +3327,7 @@ void ProtocolGame::sendCreatureWalkthrough(std::shared_ptr<Creature> creature, b writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureShield(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureShield(const std::shared_ptr<Creature> &creature) { if (!canSee(creature)) { return; } @@ -3336,7 +3339,7 @@ void ProtocolGame::sendCreatureShield(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureEmblem(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureEmblem(const std::shared_ptr<Creature> &creature) { if (!creature || !canSee(creature) || oldProtocol) { return; } @@ -3358,7 +3361,7 @@ void ProtocolGame::sendCreatureEmblem(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureSkull(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureSkull(const std::shared_ptr<Creature> &creature) { if (g_game().getWorldType() != WORLD_TYPE_PVP) { return; } @@ -3374,7 +3377,7 @@ void ProtocolGame::sendCreatureSkull(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureType(std::shared_ptr<Creature> creature, uint8_t creatureType) { +void ProtocolGame::sendCreatureType(const std::shared_ptr<Creature> &creature, uint8_t creatureType) { NetworkMessage msg; msg.addByte(0x95); msg.add<uint32_t>(creature->getID()); @@ -3394,7 +3397,7 @@ void ProtocolGame::sendCreatureType(std::shared_ptr<Creature> creature, uint8_t writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureSquare(std::shared_ptr<Creature> creature, SquareColor_t color) { +void ProtocolGame::sendCreatureSquare(const std::shared_ptr<Creature> &creature, SquareColor_t color) { if (!canSee(creature)) { return; } @@ -3477,8 +3480,8 @@ void ProtocolGame::sendCyclopediaCharacterGeneralStats() { msg.add<uint16_t>(player->getLevel()); msg.addByte(player->getLevelPercent()); msg.add<uint16_t>(player->getBaseXpGain()); // BaseXPGainRate - msg.add<uint16_t>(player->getGrindingXpBoost()); // LowLevelBonus - msg.add<uint16_t>(player->getXpBoostPercent()); // XPBoost + msg.add<uint16_t>(player->getDisplayGrindingXpBoost()); // LowLevelBonus + msg.add<uint16_t>(player->getDisplayXpBoostPercent()); // XPBoost msg.add<uint16_t>(player->getStaminaXpBoost()); // StaminaMultiplier(100=x1.0) msg.add<uint16_t>(player->getXpBoostTime()); // xpBoostRemainingTime msg.addByte(player->getXpBoostTime() > 0 ? 0x00 : 0x01); // canBuyXpBoost @@ -3543,7 +3546,7 @@ void ProtocolGame::sendCyclopediaCharacterCombatStats() { if (i == SKILL_LIFE_LEECH_CHANCE || i == SKILL_MANA_LEECH_CHANCE) { continue; } - skills_t skill = static_cast<skills_t>(i); + auto skill = static_cast<skills_t>(i); msg.add<uint16_t>(std::min<int32_t>(player->getSkillLevel(skill), std::numeric_limits<uint16_t>::max())); msg.add<uint16_t>(0); } @@ -3727,7 +3730,7 @@ void ProtocolGame::sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t writeToOutputBuffer(msg); } -void ProtocolGame::sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, std::vector<std::pair<Achievement, uint32_t>> achievementsUnlocked) { +void ProtocolGame::sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, const std::vector<std::pair<Achievement, uint32_t>> &achievementsUnlocked) { if (!player || oldProtocol) { return; } @@ -3916,7 +3919,7 @@ void ProtocolGame::sendCyclopediaCharacterOutfitsMounts() { uint16_t mountSize = 0; auto startMounts = msg.getBufferPosition(); msg.skipBytes(2); - for (const auto &mount : g_game().mounts.getMounts()) { + for (const auto &mount : g_game().mounts->getMounts()) { const std::string type = mount->type; if (player->hasMount(mount)) { ++mountSize; @@ -4081,7 +4084,7 @@ void ProtocolGame::sendCyclopediaCharacterInspection() { continue; } - msg.add<uint16_t>(imbuementInfo.imbuement->getID()); + msg.add<uint16_t>(imbuementInfo.imbuement->getIconID()); itemImbuements++; } @@ -4295,7 +4298,7 @@ void ProtocolGame::sendBasicData() { for (uint16_t sid : spellsList) { auto spell = g_spells().getInstantSpellById(sid); if (spell && spell->getSpellId() > 0) { - validSpells.push_back(spell); + validSpells.emplace_back(spell); } } @@ -4335,28 +4338,96 @@ void ProtocolGame::sendBasicData() { writeToOutputBuffer(msg); } -void ProtocolGame::sendBlessStatus() { +void ProtocolGame::sendBlessingWindow() { if (!player) { return; } NetworkMessage msg; - // uint8_t maxClientBlessings = (player->operatingSystem == CLIENTOS_NEW_WINDOWS) ? 8 : 6; (compartability for the client 10) - // Ignore ToF (bless 1) + msg.addByte(0x9B); + + bool isRetro = g_configManager().getBoolean(TOGGLE_SERVER_IS_RETRO); + + msg.addByte(isRetro ? 0x07 : 0x08); + for (auto blessing : magic_enum::enum_values<Blessings>()) { + if (isRetro && blessing == Blessings::TwistOfFate) { + continue; + } + + const auto blessingValue = enumToValue(blessing); + const auto blessingId = 1 << blessingValue; + msg.add<uint16_t>(blessingId); + msg.addByte(player->getBlessingCount(blessingValue)); + msg.addByte(player->getBlessingCount(blessingValue, true)); + } + + // Start at "The Wisdom Of Solitude" uint8_t blessCount = 0; - uint16_t flag = 0; - uint16_t pow2 = 2; - for (int i = 1; i <= 8; i++) { - if (player->hasBlessing(i)) { - if (i > 1) { - blessCount++; - } + for (auto bless : magic_enum::enum_values<Blessings>()) { + if (bless == Blessings::TwistOfFate) { + continue; + } + + if (player->hasBlessing(enumToValue(bless))) { + blessCount++; + } + } + + const auto isPromoted = player->isPromoted(); + const auto factor = (isRetro ? 6.31 : 8); + const auto skillReduction = factor * blessCount; + const auto promotionReduction = (isPromoted ? 30 : 0); + const auto minReduction = skillReduction + promotionReduction; + const auto maxLossPvpDeath = calculateMaxPvpReduction(blessCount, isPromoted); + + msg.addByte(isPromoted); + msg.addByte(30); // Reduction bonus with promotion + msg.addByte(minReduction); + msg.addByte(isRetro ? minReduction : maxLossPvpDeath); + msg.addByte(minReduction); + + const auto playerSkull = player->getSkull(); + const auto &playerAmulet = player->getThing(CONST_SLOT_NECKLACE); + bool hasSkull = (playerSkull == Skulls_t::SKULL_RED || playerSkull == Skulls_t::SKULL_BLACK); + bool usingAol = (playerAmulet && playerAmulet->getItem()->getID() == ITEM_AMULETOFLOSS); + if (hasSkull) { + msg.addByte(100); + msg.addByte(100); + } else if (usingAol) { + msg.addByte(0); + msg.addByte(0); + } else { + msg.addByte(calculateEquipmentLoss(blessCount, true)); + msg.addByte(calculateEquipmentLoss(blessCount, true)); + } + + msg.addByte(hasSkull); + msg.addByte(usingAol); + + msg.addByte(0x00); + + writeToOutputBuffer(msg); +} - flag |= pow2; +void ProtocolGame::sendBlessStatus() { + if (!player) { + return; + } + + // Ignore Twist of Fate (Id 1) + uint8_t blessCount = 0; + for (auto bless : magic_enum::enum_values<Blessings>()) { + if (bless == Blessings::TwistOfFate) { + continue; + } + if (player->hasBlessing(enumToValue(bless))) { + blessCount++; } } + NetworkMessage msg; msg.addByte(0x9C); + if (oldProtocol) { msg.add<uint16_t>(blessCount >= 5 ? 0x01 : 0x00); } else { @@ -4369,16 +4440,20 @@ void ProtocolGame::sendBlessStatus() { } void ProtocolGame::sendPremiumTrigger() { - if (!g_configManager().getBoolean(FREE_PREMIUM) && !g_configManager().getBoolean(VIP_SYSTEM_ENABLED)) { - NetworkMessage msg; - msg.addByte(0x9E); - msg.addByte(16); - for (uint16_t i = 0; i <= 15; i++) { - // PREMIUM_TRIGGER_TRAIN_OFFLINE = false, PREMIUM_TRIGGER_XP_BOOST = false, PREMIUM_TRIGGER_MARKET = false, PREMIUM_TRIGGER_VIP_LIST = false, PREMIUM_TRIGGER_DEPOT_SPACE = false, PREMIUM_TRIGGER_INVITE_PRIVCHAT = false - msg.addByte(0x01); - } - writeToOutputBuffer(msg); + if (g_configManager().getBoolean(FREE_PREMIUM) || g_configManager().getBoolean(VIP_SYSTEM_ENABLED)) { + return; } + + NetworkMessage msg; + msg.addByte(0x9E); + + msg.addByte(16); + for (uint16_t i = 0; i <= 15; i++) { + // PREMIUM_TRIGGER_TRAIN_OFFLINE = false, PREMIUM_TRIGGER_XP_BOOST = false, PREMIUM_TRIGGER_MARKET = false, PREMIUM_TRIGGER_VIP_LIST = false, PREMIUM_TRIGGER_DEPOT_SPACE = false, PREMIUM_TRIGGER_INVITE_PRIVCHAT = false + msg.addByte(0x01); + } + + writeToOutputBuffer(msg); } void ProtocolGame::sendTextMessage(const TextMessage &message) { @@ -4606,8 +4681,8 @@ void ProtocolGame::sendUnjustifiedPoints(const uint8_t &dayProgress, const uint8 writeToOutputBuffer(msg); } -void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr<Container> container, bool hasParent, uint16_t firstIndex) { - if (!player) { +void ProtocolGame::sendContainer(uint8_t cid, const std::shared_ptr<Container> &container, bool hasParent, uint16_t firstIndex) { + if (!player || !container) { return; } @@ -4665,7 +4740,7 @@ void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr<Container> contain msg.addByte(std::min<uint32_t>(maxItemsToSend, containerSize)); uint32_t i = 0; - for (ItemDeque::const_iterator it = itemList.begin() + firstIndex, end = itemList.end(); i < maxItemsToSend && it != end; ++it, ++i) { + for (auto it = itemList.begin() + firstIndex, end = itemList.end(); i < maxItemsToSend && it != end; ++it, ++i) { AddItem(msg, *it); } } @@ -4731,7 +4806,7 @@ void ProtocolGame::sendLootContainers() { msg.addByte(player->quickLootFallbackToMainContainer ? 1 : 0); std::map<ObjectCategory_t, std::pair<std::shared_ptr<Container>, std::shared_ptr<Container>>> managedContainersMap; - for (auto [category, containersPair] : player->m_managedContainers) { + for (const auto &[category, containersPair] : player->m_managedContainers) { if (containersPair.first && !containersPair.first->isRemoved()) { managedContainersMap[category].first = containersPair.first; } @@ -4743,7 +4818,7 @@ void ProtocolGame::sendLootContainers() { auto msgPosition = msg.getBufferPosition(); msg.skipBytes(1); uint8_t containers = 0; - for (auto [category, containersPair] : managedContainersMap) { + for (const auto &[category, containersPair] : managedContainersMap) { if (!isValidObjectCategory(category)) { continue; } @@ -4760,7 +4835,7 @@ void ProtocolGame::sendLootContainers() { writeToOutputBuffer(msg); } -void ProtocolGame::sendLootStats(std::shared_ptr<Item> item, uint8_t count) { +void ProtocolGame::sendLootStats(const std::shared_ptr<Item> &item, uint8_t count) { if (!item) { return; } @@ -4784,7 +4859,7 @@ void ProtocolGame::sendLootStats(std::shared_ptr<Item> item, uint8_t count) { lootedItem = nullptr; } -void ProtocolGame::sendShop(std::shared_ptr<Npc> npc) { +void ProtocolGame::sendShop(const std::shared_ptr<Npc> &npc) { Benchmark brenchmark; NetworkMessage msg; msg.addByte(0x7A); @@ -5028,8 +5103,8 @@ void ProtocolGame::updateCoinBalance() { [playerId = player->getID()] { const auto &threadPlayer = g_game().getPlayerByID(playerId); if (threadPlayer && threadPlayer->getAccount()) { - const auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Normal)); - const auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + const auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(CoinType::Normal); + const auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(CoinType::Transferable); threadPlayer->coinBalance = coins; threadPlayer->coinTransferableBalance = transferCoins; @@ -5471,8 +5546,8 @@ void ProtocolGame::sendOpenForge() { msg.add<uint16_t>(convergenceFusionCount); msg.setBufferPosition(transferTotalCountPosition); - auto transferTotalCount = getIterationIncreaseCount(donorTierItemMap); - msg.addByte(static_cast<uint8_t>(transferTotalCount)); + auto transferTotalCount = donorTierItemMap.size(); + msg.addByte(transferTotalCount); if (transferTotalCount > 0) { for (const auto &[itemId, tierAndCountMap] : donorTierItemMap) { // Let's access the itemType to check the item's (donator of tier) classification level @@ -5484,7 +5559,7 @@ void ProtocolGame::sendOpenForge() { } // Total count of item (donator of tier) - auto donorTierTotalItemsCount = getIterationIncreaseCount(tierAndCountMap); + auto donorTierTotalItemsCount = tierAndCountMap.size(); msg.add<uint16_t>(donorTierTotalItemsCount); for (const auto &[donorItemTier, donorItemCount] : tierAndCountMap) { msg.add<uint16_t>(itemId); @@ -5669,20 +5744,27 @@ void ProtocolGame::sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId void ProtocolGame::sendForgeHistory(uint8_t page) { page = page + 1; auto historyVector = player->getForgeHistory(); - auto historyVectorLen = getVectorIterationIncreaseCount(historyVector); + auto historyVectorLen = historyVector.size(); - uint16_t lastPage = (1 < std::floor((historyVectorLen - 1) / 9) + 1) ? static_cast<uint16_t>(std::floor((historyVectorLen - 1) / 9) + 1) : 1; - uint16_t currentPage = (lastPage < page) ? lastPage : page; + uint16_t currentPage = 1; + uint16_t lastPage = 1; + uint16_t pageFirstEntry = 0; + uint16_t pageLastEntry = 0; std::vector<ForgeHistory> historyPerPage; - uint16_t pageFirstEntry = (0 < historyVectorLen - (currentPage - 1) * 9) ? historyVectorLen - (currentPage - 1) * 9 : 0; - uint16_t pageLastEntry = (0 < historyVectorLen - currentPage * 9) ? historyVectorLen - currentPage * 9 : 0; - for (uint16_t entry = pageFirstEntry; entry > pageLastEntry; --entry) { - historyPerPage.push_back(historyVector[entry - 1]); - } + if (historyVectorLen > 0) { + lastPage = std::clamp<uint16_t>(std::floor((historyVectorLen - 1) / 9) + 1, 0, std::numeric_limits<uint16_t>::max()); + currentPage = (lastPage < page) ? lastPage : page; - auto historyPageToSend = getVectorIterationIncreaseCount(historyPerPage); + pageFirstEntry = std::clamp<uint16_t>(historyVectorLen - (currentPage - 1) * 9, 0, std::numeric_limits<uint16_t>::max()); + pageLastEntry = historyVectorLen > currentPage * 9 ? std::clamp<uint16_t>(historyVectorLen - currentPage * 9, 0, std::numeric_limits<uint16_t>::max()) : 0; + for (uint16_t entry = pageFirstEntry; entry > pageLastEntry; --entry) { + historyPerPage.emplace_back(historyVector[entry - 1]); + } + } + + auto historyPageToSend = historyPerPage.size(); NetworkMessage msg; msg.addByte(0x88); msg.add<uint16_t>(currentPage - 1); // Current page @@ -5753,16 +5835,19 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { ss << static_cast<uint16_t>(it.shootRange) << " fields"; } msg.addString(ss.str()); - } else if (!it.isRanged() && it.attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - std::ostringstream ss; - ss << it.attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - msg.addString(ss.str()); - } else { - msg.addString(std::to_string(it.attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); } - } else { - msg.add<uint16_t>(0x00); + + if (it.attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", it.attack, attackDescription); + } else if (it.attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(it.attack); + } + + msg.addString(attackDescription); } if (it.isContainer()) { @@ -5870,7 +5955,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { separator = true; } - ss << fmt::format("{} {:+.2f}%", getSkillName(i), skills / 100.0); + ss << fmt::format("{} {:+}%", getSkillName(i), skills / 100.0); } if (it.abilities->stats[STAT_MAGICPOINTS] != 0) { @@ -6085,7 +6170,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { writeToOutputBuffer(msg); } -void ProtocolGame::sendTradeItemRequest(const std::string &traderName, std::shared_ptr<Item> item, bool ack) { +void ProtocolGame::sendTradeItemRequest(const std::string &traderName, const std::shared_ptr<Item> &item, bool ack) { NetworkMessage msg; if (ack) { @@ -6104,9 +6189,9 @@ void ProtocolGame::sendTradeItemRequest(const std::string &traderName, std::shar for (const auto &containerItem : container->getItemList()) { const auto &tmpContainer = containerItem->getContainer(); if (tmpContainer) { - listContainer.push_back(tmpContainer); + listContainer.emplace_back(tmpContainer); } - itemList.push_back(containerItem); + itemList.emplace_back(containerItem); } // Removes the object after processing everything, avoiding memory usage after freeing @@ -6137,7 +6222,7 @@ void ProtocolGame::sendCloseContainer(uint8_t cid) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureTurn(std::shared_ptr<Creature> creature, uint32_t stackPos) { +void ProtocolGame::sendCreatureTurn(const std::shared_ptr<Creature> &creature, uint32_t stackPos) { if (!canSee(creature)) { return; } @@ -6153,7 +6238,7 @@ void ProtocolGame::sendCreatureTurn(std::shared_ptr<Creature> creature, uint32_t writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, const Position* pos /* = nullptr*/) { +void ProtocolGame::sendCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, const Position* pos /* = nullptr*/) { NetworkMessage msg; msg.addByte(0xAA); @@ -6189,7 +6274,7 @@ void ProtocolGame::sendCreatureSay(std::shared_ptr<Creature> creature, SpeakClas writeToOutputBuffer(msg); } -void ProtocolGame::sendToChannel(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, uint16_t channelId) { +void ProtocolGame::sendToChannel(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, uint16_t channelId) { NetworkMessage msg; msg.addByte(0xAA); @@ -6231,7 +6316,7 @@ void ProtocolGame::sendToChannel(std::shared_ptr<Creature> creature, SpeakClasse writeToOutputBuffer(msg); } -void ProtocolGame::sendPrivateMessage(std::shared_ptr<Player> speaker, SpeakClasses type, const std::string &text) { +void ProtocolGame::sendPrivateMessage(const std::shared_ptr<Player> &speaker, SpeakClasses type, const std::string &text) { NetworkMessage msg; msg.addByte(0xAA); static uint32_t statementId = 0; @@ -6266,7 +6351,7 @@ void ProtocolGame::sendCancelTarget() { writeToOutputBuffer(msg); } -void ProtocolGame::sendChangeSpeed(std::shared_ptr<Creature> creature, uint16_t speed) { +void ProtocolGame::sendChangeSpeed(const std::shared_ptr<Creature> &creature, uint16_t speed) { NetworkMessage msg; msg.addByte(0x8F); msg.add<uint32_t>(creature->getID()); @@ -6406,7 +6491,7 @@ void ProtocolGame::removeMagicEffect(const Position &pos, uint16_t type) { writeToOutputBuffer(msg); } -void ProtocolGame::sendCreatureHealth(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendCreatureHealth(const std::shared_ptr<Creature> &creature) { if (creature->isHealthHidden()) { return; } @@ -6423,7 +6508,7 @@ void ProtocolGame::sendCreatureHealth(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyCreatureUpdate(std::shared_ptr<Creature> target) { +void ProtocolGame::sendPartyCreatureUpdate(const std::shared_ptr<Creature> &target) { if (!player || oldProtocol) { return; } @@ -6441,7 +6526,7 @@ void ProtocolGame::sendPartyCreatureUpdate(std::shared_ptr<Creature> target) { writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyCreatureShield(std::shared_ptr<Creature> target) { +void ProtocolGame::sendPartyCreatureShield(const std::shared_ptr<Creature> &target) { uint32_t cid = target->getID(); if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); @@ -6455,7 +6540,7 @@ void ProtocolGame::sendPartyCreatureShield(std::shared_ptr<Creature> target) { writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyCreatureSkull(std::shared_ptr<Creature> target) { +void ProtocolGame::sendPartyCreatureSkull(const std::shared_ptr<Creature> &target) { if (g_game().getWorldType() != WORLD_TYPE_PVP) { return; } @@ -6473,7 +6558,7 @@ void ProtocolGame::sendPartyCreatureSkull(std::shared_ptr<Creature> target) { writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyCreatureHealth(std::shared_ptr<Creature> target, uint8_t healthPercent) { +void ProtocolGame::sendPartyCreatureHealth(const std::shared_ptr<Creature> &target, uint8_t healthPercent) { uint32_t cid = target->getID(); if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); @@ -6487,7 +6572,7 @@ void ProtocolGame::sendPartyCreatureHealth(std::shared_ptr<Creature> target, uin writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyPlayerMana(std::shared_ptr<Player> target, uint8_t manaPercent) { +void ProtocolGame::sendPartyPlayerMana(const std::shared_ptr<Player> &target, uint8_t manaPercent) { uint32_t cid = target->getID(); if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); @@ -6505,7 +6590,7 @@ void ProtocolGame::sendPartyPlayerMana(std::shared_ptr<Player> target, uint8_t m writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyCreatureShowStatus(std::shared_ptr<Creature> target, bool showStatus) { +void ProtocolGame::sendPartyCreatureShowStatus(const std::shared_ptr<Creature> &target, bool showStatus) { uint32_t cid = target->getID(); if (!knownCreatureSet.contains(cid)) { sendPartyCreatureUpdate(target); @@ -6523,7 +6608,7 @@ void ProtocolGame::sendPartyCreatureShowStatus(std::shared_ptr<Creature> target, writeToOutputBuffer(msg); } -void ProtocolGame::sendPartyPlayerVocation(std::shared_ptr<Player> target) { +void ProtocolGame::sendPartyPlayerVocation(const std::shared_ptr<Player> &target) { if (!target) { return; } @@ -6546,7 +6631,7 @@ void ProtocolGame::sendPartyPlayerVocation(std::shared_ptr<Player> target) { writeToOutputBuffer(msg); } -void ProtocolGame::sendPlayerVocation(std::shared_ptr<Player> target) { +void ProtocolGame::sendPlayerVocation(const std::shared_ptr<Player> &target) { if (!player || !target || oldProtocol) { return; } @@ -6575,7 +6660,7 @@ void ProtocolGame::sendMapDescription(const Position &pos) { writeToOutputBuffer(msg); } -void ProtocolGame::sendAddTileItem(const Position &pos, uint32_t stackpos, std::shared_ptr<Item> item) { +void ProtocolGame::sendAddTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr<Item> &item) { if (!canSee(pos)) { return; } @@ -6588,7 +6673,7 @@ void ProtocolGame::sendAddTileItem(const Position &pos, uint32_t stackpos, std:: writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateTileItem(const Position &pos, uint32_t stackpos, std::shared_ptr<Item> item) { +void ProtocolGame::sendUpdateTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr<Item> &item) { if (!canSee(pos)) { return; } @@ -6611,7 +6696,7 @@ void ProtocolGame::sendRemoveTileThing(const Position &pos, uint32_t stackpos) { writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateTileCreature(const Position &pos, uint32_t stackpos, const std::shared_ptr<Creature> creature) { +void ProtocolGame::sendUpdateTileCreature(const Position &pos, uint32_t stackpos, const std::shared_ptr<Creature> &creature) { if (!canSee(pos)) { return; } @@ -6628,7 +6713,7 @@ void ProtocolGame::sendUpdateTileCreature(const Position &pos, uint32_t stackpos writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateTile(std::shared_ptr<Tile> tile, const Position &pos) { +void ProtocolGame::sendUpdateTile(const std::shared_ptr<Tile> &tile, const Position &pos) { if (!canSee(pos)) { return; } @@ -6686,7 +6771,7 @@ void ProtocolGame::sendAllowBugReport() { writeToOutputBuffer(msg); } -void ProtocolGame::sendAddCreature(std::shared_ptr<Creature> creature, const Position &pos, int32_t stackpos, bool isLogin) { +void ProtocolGame::sendAddCreature(const std::shared_ptr<Creature> &creature, const Position &pos, int32_t stackpos, bool isLogin) { if (!canSee(pos)) { return; } @@ -6841,7 +6926,7 @@ void ProtocolGame::sendAddCreature(std::shared_ptr<Creature> creature, const Pos } } -void ProtocolGame::sendMoveCreature(std::shared_ptr<Creature> creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport) { +void ProtocolGame::sendMoveCreature(const std::shared_ptr<Creature> &creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport) { if (creature == player) { if (oldStackPos >= 10) { sendMapDescription(newPos); @@ -6903,7 +6988,7 @@ void ProtocolGame::sendMoveCreature(std::shared_ptr<Creature> creature, const Po } } -void ProtocolGame::sendInventoryItem(Slots_t slot, std::shared_ptr<Item> item) { +void ProtocolGame::sendInventoryItem(Slots_t slot, const std::shared_ptr<Item> &item) { NetworkMessage msg; if (item) { msg.addByte(0x78); @@ -6945,7 +7030,7 @@ void ProtocolGame::sendInventoryIds() { writeToOutputBuffer(msg); } -void ProtocolGame::sendAddContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> item) { +void ProtocolGame::sendAddContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &item) { NetworkMessage msg; msg.addByte(0x70); msg.addByte(cid); @@ -6954,7 +7039,7 @@ void ProtocolGame::sendAddContainerItem(uint8_t cid, uint16_t slot, std::shared_ writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> item) { +void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &item) { NetworkMessage msg; msg.addByte(0x71); msg.addByte(cid); @@ -6963,7 +7048,7 @@ void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint16_t slot, std::shar writeToOutputBuffer(msg); } -void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> lastItem) { +void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &lastItem) { NetworkMessage msg; msg.addByte(0x72); msg.addByte(cid); @@ -6976,7 +7061,7 @@ void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot, std::shar writeToOutputBuffer(msg); } -void ProtocolGame::sendTextWindow(uint32_t windowTextId, std::shared_ptr<Item> item, uint16_t maxlen, bool canWrite) { +void ProtocolGame::sendTextWindow(uint32_t windowTextId, const std::shared_ptr<Item> &item, uint16_t maxlen, bool canWrite) { NetworkMessage msg; msg.addByte(0x96); msg.add<uint32_t>(windowTextId); @@ -7047,7 +7132,7 @@ void ProtocolGame::sendOutfitWindow() { bool mounted = false; if (!isSupportOutfit) { - const auto currentMount = g_game().mounts.getMountByID(player->getLastMount()); + const auto currentMount = g_game().mounts->getMountByID(player->getLastMount()); if (currentMount) { mounted = (currentOutfit.lookMount == currentMount->clientId); currentOutfit.lookMount = currentMount->clientId; @@ -7083,9 +7168,9 @@ void ProtocolGame::sendOutfitWindow() { } std::vector<std::shared_ptr<Mount>> mounts; - for (const auto &mount : g_game().mounts.getMounts()) { + for (const auto &mount : g_game().mounts->getMounts()) { if (player->hasMount(mount)) { - mounts.push_back(mount); + mounts.emplace_back(mount); } } @@ -7181,7 +7266,7 @@ void ProtocolGame::sendOutfitWindow() { uint16_t mountSize = 0; msg.skipBytes(2); - const auto mounts = g_game().mounts.getMounts(); + const auto mounts = g_game().mounts->getMounts(); for (const auto &mount : mounts) { if (player->hasMount(mount)) { msg.add<uint16_t>(mount->clientId); @@ -7240,7 +7325,7 @@ void ProtocolGame::sendOutfitWindow() { writeToOutputBuffer(msg); } -void ProtocolGame::sendPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackpos) { +void ProtocolGame::sendPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos) { if (!podium || oldProtocol) { g_logger().error("[{}] item is nullptr", __FUNCTION__); return; @@ -7301,7 +7386,7 @@ void ProtocolGame::sendPodiumWindow(std::shared_ptr<Item> podium, const Position uint16_t mountSize = 0; msg.skipBytes(2); - const auto mounts = g_game().mounts.getMounts(); + const auto mounts = g_game().mounts->getMounts(); for (const auto &mount : mounts) { if (player->hasMount(mount)) { msg.add<uint16_t>(mount->clientId); @@ -7456,7 +7541,7 @@ void ProtocolGame::sendPreyData(const std::unique_ptr<PreySlot> &slot) { std::vector<uint16_t> validRaceIds; for (auto raceId : slot->raceIdList) { if (g_monsters().getMonsterTypeByRaceId(raceId)) { - validRaceIds.push_back(raceId); + validRaceIds.emplace_back(raceId); } else { g_logger().error("[ProtocolGame::sendPreyData] - Unknown monster type raceid: {}, removing prey slot from player {}", raceId, player->getName()); // Remove wrong raceid from slot @@ -7622,7 +7707,7 @@ void ProtocolGame::sendModalWindow(const ModalWindow &modalWindow) { } ////////////// Add common messages -void ProtocolGame::AddCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, bool known, uint32_t remove) { +void ProtocolGame::AddCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, bool known, uint32_t remove) { CreatureType_t creatureType = creature->getType(); std::shared_ptr<Player> otherPlayer = creature->getPlayer(); @@ -7764,8 +7849,8 @@ void ProtocolGame::AddPlayerStats(NetworkMessage &msg) { msg.add<uint16_t>(player->getVoucherXpBoost()); // xp voucher } - msg.add<uint16_t>(player->getGrindingXpBoost()); // low level bonus - msg.add<uint16_t>(player->getXpBoostPercent()); // xp boost + msg.add<uint16_t>(player->getDisplayGrindingXpBoost()); // low level bonus + msg.add<uint16_t>(player->getDisplayXpBoostPercent()); // xp boost msg.add<uint16_t>(player->getStaminaXpBoost()); // stamina multiplier (100 = 1.0x) if (!oldProtocol) { @@ -7805,7 +7890,7 @@ void ProtocolGame::AddPlayerSkills(NetworkMessage &msg) { if (oldProtocol) { for (uint8_t i = SKILL_FIRST; i <= SKILL_FISHING; ++i) { - skills_t skill = static_cast<skills_t>(i); + auto skill = static_cast<skills_t>(i); msg.add<uint16_t>(std::min<int32_t>(player->getSkillLevel(skill), std::numeric_limits<uint16_t>::max())); msg.add<uint16_t>(player->getBaseSkill(skill)); msg.addByte(std::min<uint8_t>(100, static_cast<uint8_t>(player->getSkillPercent(skill)))); @@ -7817,7 +7902,7 @@ void ProtocolGame::AddPlayerSkills(NetworkMessage &msg) { msg.add<uint16_t>(player->getMagicLevelPercent() * 100); for (uint8_t i = SKILL_FIRST; i <= SKILL_FISHING; ++i) { - skills_t skill = static_cast<skills_t>(i); + auto skill = static_cast<skills_t>(i); msg.add<uint16_t>(std::min<int32_t>(player->getSkillLevel(skill), std::numeric_limits<uint16_t>::max())); msg.add<uint16_t>(player->getBaseSkill(skill)); msg.add<uint16_t>(player->getLoyaltySkill(skill)); @@ -7829,7 +7914,7 @@ void ProtocolGame::AddPlayerSkills(NetworkMessage &msg) { if (!oldProtocol && (i == SKILL_LIFE_LEECH_CHANCE || i == SKILL_MANA_LEECH_CHANCE)) { continue; } - skills_t skill = static_cast<skills_t>(i); + auto skill = static_cast<skills_t>(i); msg.add<uint16_t>(std::min<int32_t>(player->getSkillLevel(skill), std::numeric_limits<uint16_t>::max())); msg.add<uint16_t>(player->getBaseSkill(skill)); } @@ -7893,7 +7978,7 @@ void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) c msg.add<uint32_t>(baseImbuement->protectionPrice); } -void ProtocolGame::openImbuementWindow(std::shared_ptr<Item> item) { +void ProtocolGame::openImbuementWindow(const std::shared_ptr<Item> &item) { if (!item || item->isRemoved()) { return; } @@ -7960,7 +8045,7 @@ void ProtocolGame::sendMessageDialog(const std::string &message) { writeToOutputBuffer(msg); } -void ProtocolGame::sendImbuementResult(const std::string message) { +void ProtocolGame::sendImbuementResult(const std::string &message) { NetworkMessage msg; msg.addByte(0xED); msg.addByte(0x01); @@ -7992,7 +8077,7 @@ void ProtocolGame::sendSpecialContainersAvailable() { writeToOutputBuffer(msg); } -void ProtocolGame::updatePartyTrackerAnalyzer(const std::shared_ptr<Party> party) { +void ProtocolGame::updatePartyTrackerAnalyzer(const std::shared_ptr<Party> &party) { if (oldProtocol || !player || !party || !party->getLeader()) { return; } @@ -8032,7 +8117,7 @@ void ProtocolGame::updatePartyTrackerAnalyzer(const std::shared_ptr<Party> party writeToOutputBuffer(msg); } -void ProtocolGame::AddCreatureLight(NetworkMessage &msg, std::shared_ptr<Creature> creature) { +void ProtocolGame::AddCreatureLight(NetworkMessage &msg, const std::shared_ptr<Creature> &creature) { LightInfo lightInfo = creature->getCreatureLight(); msg.addByte(0x8D); @@ -8052,7 +8137,7 @@ void ProtocolGame::RemoveTileThing(NetworkMessage &msg, const Position &pos, uin msg.addByte(static_cast<uint8_t>(stackpos)); } -void ProtocolGame::sendKillTrackerUpdate(std::shared_ptr<Container> corpse, const std::string &name, const Outfit_t creatureOutfit) { +void ProtocolGame::sendKillTrackerUpdate(const std::shared_ptr<Container> &corpse, const std::string &name, const Outfit_t creatureOutfit) { if (oldProtocol) { return; } @@ -8079,7 +8164,7 @@ void ProtocolGame::sendKillTrackerUpdate(std::shared_ptr<Container> corpse, cons writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateSupplyTracker(std::shared_ptr<Item> item) { +void ProtocolGame::sendUpdateSupplyTracker(const std::shared_ptr<Item> &item) { if (oldProtocol || !player || !item) { return; } @@ -8114,7 +8199,7 @@ void ProtocolGame::sendUpdateImpactTracker(CombatType_t type, int32_t amount) { writeToOutputBuffer(msg); } -void ProtocolGame::sendUpdateInputAnalyzer(CombatType_t type, int32_t amount, std::string target) { +void ProtocolGame::sendUpdateInputAnalyzer(CombatType_t type, int32_t amount, const std::string &target) { if (!player || oldProtocol) { return; } @@ -8203,7 +8288,7 @@ void ProtocolGame::sendTaskHuntingData(const std::unique_ptr<TaskHuntingSlot> &s writeToOutputBuffer(msg); } -void ProtocolGame::MoveUpCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, const Position &newPos, const Position &oldPos) { +void ProtocolGame::MoveUpCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, const Position &newPos, const Position &oldPos) { if (creature != player) { return; } @@ -8247,7 +8332,7 @@ void ProtocolGame::MoveUpCreature(NetworkMessage &msg, std::shared_ptr<Creature> GetMapDescription(oldPos.x - MAP_MAX_CLIENT_VIEW_PORT_X, oldPos.y - MAP_MAX_CLIENT_VIEW_PORT_Y, newPos.z, (MAP_MAX_CLIENT_VIEW_PORT_X + 1) * 2, 1, msg); } -void ProtocolGame::MoveDownCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, const Position &newPos, const Position &oldPos) { +void ProtocolGame::MoveDownCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, const Position &newPos, const Position &oldPos) { if (creature != player) { return; } @@ -8366,7 +8451,7 @@ void ProtocolGame::parseInventoryImbuements(NetworkMessage &msg) { g_game().playerRequestInventoryImbuements(player->getID(), isTrackerOpen); } -void ProtocolGame::sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> items) { +void ProtocolGame::sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> &items) { if (oldProtocol) { return; } @@ -8458,7 +8543,7 @@ void ProtocolGame::sendItemsPrice() { writeToOutputBuffer(msg); } -void ProtocolGame::reloadCreature(std::shared_ptr<Creature> creature) { +void ProtocolGame::reloadCreature(const std::shared_ptr<Creature> &creature) { if (!creature || !canSee(creature)) { return; } @@ -8520,11 +8605,11 @@ void ProtocolGame::parseStashWithdraw(NetworkMessage &msg) { return; } - Supply_Stash_Actions_t action = static_cast<Supply_Stash_Actions_t>(msg.getByte()); + auto action = static_cast<Supply_Stash_Actions_t>(msg.getByte()); switch (action) { case SUPPLY_STASH_ACTION_STOW_ITEM: { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); uint32_t count = msg.getByte(); g_game().playerStowItem(player->getID(), pos, itemId, stackpos, count, false); @@ -8532,21 +8617,21 @@ void ProtocolGame::parseStashWithdraw(NetworkMessage &msg) { } case SUPPLY_STASH_ACTION_STOW_CONTAINER: { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerStowItem(player->getID(), pos, itemId, stackpos, 0, false); break; } case SUPPLY_STASH_ACTION_STOW_STACK: { Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); g_game().playerStowItem(player->getID(), pos, itemId, stackpos, 0, true); break; } case SUPPLY_STASH_ACTION_WITHDRAW: { - uint16_t itemId = msg.get<uint16_t>(); - uint32_t count = msg.get<uint32_t>(); + auto itemId = msg.get<uint16_t>(); + auto count = msg.get<uint32_t>(); uint8_t stackpos = msg.getByte(); g_game().playerStashWithdraw(player->getID(), itemId, count, stackpos); break; @@ -8657,7 +8742,7 @@ void ProtocolGame::parseDepotSearchItemRequest(NetworkMessage &msg) { return; } - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t itemTier = 0; if (Item::items[itemId].upgradeClassification > 0) { itemTier = msg.getByte(); @@ -8671,7 +8756,7 @@ void ProtocolGame::parseRetrieveDepotSearch(NetworkMessage &msg) { return; } - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t itemTier = 0; if (Item::items[itemId].upgradeClassification > 0) { itemTier = msg.getByte(); @@ -8690,7 +8775,7 @@ void ProtocolGame::parseOpenParentContainer(NetworkMessage &msg) { g_game().playerRequestOpenContainerFromDepotSearch(player->getID(), pos); } -void ProtocolGame::sendUpdateCreature(std::shared_ptr<Creature> creature) { +void ProtocolGame::sendUpdateCreature(const std::shared_ptr<Creature> &creature) { if (oldProtocol || !creature || !player) { return; } @@ -8717,7 +8802,7 @@ void ProtocolGame::sendUpdateCreature(std::shared_ptr<Creature> creature) { writeToOutputBuffer(msg); } -void ProtocolGame::getForgeInfoMap(std::shared_ptr<Item> item, std::map<uint16_t, std::map<uint8_t, uint16_t>> &itemsMap) const { +void ProtocolGame::getForgeInfoMap(const std::shared_ptr<Item> &item, std::map<uint16_t, std::map<uint8_t, uint16_t>> &itemsMap) const { std::map<uint8_t, uint16_t> itemInfo; itemInfo.insert({ item->getTier(), item->getItemCount() }); auto [first, inserted] = itemsMap.try_emplace(item->getID(), itemInfo); @@ -8737,7 +8822,7 @@ void ProtocolGame::sendForgeSkillStats(NetworkMessage &msg) const { std::vector<Slots_t> slots { CONST_SLOT_LEFT, CONST_SLOT_ARMOR, CONST_SLOT_HEAD, CONST_SLOT_LEGS }; for (const auto &slot : slots) { double_t skill = 0; - if (std::shared_ptr<Item> item = player->getInventoryItem(slot); item) { + if (const auto &item = player->getInventoryItem(slot); item) { const ItemType &it = Item::items[item->getID()]; if (it.isWeapon()) { skill = item->getFatalChance() * 100; @@ -8846,7 +8931,11 @@ void ProtocolGame::parseSendBosstiarySlots() { uint32_t boostedBossId = g_ioBosstiary().getBoostedBossId(); // Sanity checks - std::string boostedBossName = g_ioBosstiary().getBoostedBossName(); + const std::string &boostedBossName = g_ioBosstiary().getBoostedBossName(); + if (boostedBossName.empty()) { + g_logger().error("[{}] The boosted boss name is empty", __FUNCTION__); + return; + } const auto mTypeBoosted = g_monsters().getMonsterType(boostedBossName); auto boostedBossRace = mTypeBoosted ? mTypeBoosted->info.bosstiaryRace : BosstiaryRarity_t::BOSS_INVALID; auto isValidBoostedBoss = boostedBossId == 0 || (boostedBossRace >= BosstiaryRarity_t::RARITY_BANE && boostedBossRace <= BosstiaryRarity_t::RARITY_NEMESIS); @@ -8973,7 +9062,7 @@ void ProtocolGame::parseBosstiarySlot(NetworkMessage &msg) { } uint8_t slotBossId = msg.getByte(); - uint32_t selectedBossId = msg.get<uint32_t>(); + auto selectedBossId = msg.get<uint32_t>(); g_game().playerBosstiarySlot(player->getID(), slotBossId, selectedBossId); } @@ -9016,7 +9105,7 @@ void ProtocolGame::sendPodiumDetails(NetworkMessage &msg, const std::vector<uint } } -void ProtocolGame::sendMonsterPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackPos) { +void ProtocolGame::sendMonsterPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackPos) { if (!podium || oldProtocol) { g_logger().error("[{}] item is nullptr", __FUNCTION__); return; @@ -9081,9 +9170,9 @@ void ProtocolGame::parseSetMonsterPodium(NetworkMessage &msg) const { } // For some reason the cip sends uint32_t, but we use uint16_t, so let's just ignore that - uint16_t monsterRaceId = (uint16_t)msg.get<uint32_t>(); + auto monsterRaceId = static_cast<uint16_t>(msg.get<uint32_t>()); Position pos = msg.getPosition(); - uint16_t itemId = msg.get<uint16_t>(); + auto itemId = msg.get<uint16_t>(); uint8_t stackpos = msg.getByte(); uint8_t direction = msg.getByte(); uint8_t podiumVisible = msg.getByte(); diff --git a/src/server/network/protocol/protocolgame.hpp b/src/server/network/protocol/protocolgame.hpp index fc27cd3abfc..2048bea7c16 100644 --- a/src/server/network/protocol/protocolgame.hpp +++ b/src/server/network/protocol/protocolgame.hpp @@ -10,12 +10,25 @@ #pragma once #include "server/network/protocol/protocol.hpp" -#include "creatures/interactions/chat.hpp" -#include "creatures/creature.hpp" -#include "enums/forge_conversion.hpp" -#include "creatures/players/cyclopedia/player_badge.hpp" -#include "creatures/players/cyclopedia/player_cyclopedia.hpp" -#include "creatures/players/cyclopedia/player_title.hpp" +#include "game/movement/position.hpp" +#include "utils/utils_definitions.hpp" + +enum class PlayerIcon : uint8_t; +enum class IconBakragore : uint8_t; +enum class ForgeAction_t : uint8_t; +enum MessageClasses : uint8_t; +enum ReturnValue : uint16_t; +enum TextColor_t : uint8_t; +enum OperatingSystem_t : uint8_t; +enum ChannelEvent_t : uint8_t; +enum CyclopediaCharacterInfoType_t : uint8_t; +enum Resource_t : uint8_t; +enum class VipStatus_t : uint8_t; +enum SpellGroup_t : uint8_t; +enum Slots_t : uint8_t; +enum CombatType_t : uint8_t; +enum SoundEffect_t : uint16_t; +enum class SourceEffect_t : uint8_t; class NetworkMessage; class Player; @@ -25,18 +38,36 @@ class House; class Container; class Tile; class Connection; -class Quest; class ProtocolGame; class PreySlot; class TaskHuntingSlot; class TaskHuntingOption; +class Item; +class Party; +class Creature; +class MonsterType; +class Npc; struct ModalWindow; +struct Position; +struct Outfit_t; +struct RecentDeathEntry; +struct RecentPvPKillEntry; struct Achievement; -struct Badge; -struct Title; +struct MarketOffer; +struct ShopBlock; +struct MarketOfferEx; +struct HistoryMarketOffer; +struct LightInfo; using ProtocolGame_ptr = std::shared_ptr<ProtocolGame>; +using ItemVector = std::vector<std::shared_ptr<Item>>; +using InvitedMap = std::map<uint32_t, std::shared_ptr<Player>>; +using UsersMap = std::map<uint32_t, std::shared_ptr<Player>>; +using MarketOfferList = std::list<MarketOffer>; +using HistoryMarketOfferList = std::list<HistoryMarketOffer>; +using ItemsTierCountList = std::map<uint16_t, std::map<uint8_t, uint32_t>>; +using StashItemList = std::map<uint16_t, uint32_t>; struct TextMessage { TextMessage() = default; @@ -66,13 +97,13 @@ class ProtocolGame final : public Protocol { return "gameworld protocol"; } - explicit ProtocolGame(Connection_ptr initConnection); + explicit ProtocolGame(const Connection_ptr &initConnection); void login(const std::string &name, uint32_t accnumber, OperatingSystem_t operatingSystem); void logout(bool displayEffect, bool forced); - void AddItem(NetworkMessage &msg, std::shared_ptr<Item> item); - void AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier); + void AddItem(NetworkMessage &msg, const std::shared_ptr<Item> &item); + void AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier) const; uint16_t getVersion() const { return version; @@ -91,7 +122,7 @@ class ProtocolGame final : public Protocol { void checkCreatureAsKnown(uint32_t id, bool &known, uint32_t &removedKnown); bool canSee(int32_t x, int32_t y, int32_t z) const; - bool canSee(std::shared_ptr<Creature>) const; + bool canSee(const std::shared_ptr<Creature> &) const; bool canSee(const Position &pos) const; // we have all the parse methods @@ -129,7 +160,7 @@ class ProtocolGame final : public Protocol { void sendSessionEndInformation(SessionEndInformations information); - void sendItemInspection(uint16_t itemId, uint8_t itemCount, std::shared_ptr<Item> item, bool cyclopedia); + void sendItemInspection(uint16_t itemId, uint8_t itemCount, const std::shared_ptr<Item> &item, bool cyclopedia); void parseInspectionObject(NetworkMessage &msg); void parseFriendSystemAction(NetworkMessage &msg); @@ -162,7 +193,6 @@ class ProtocolGame final : public Protocol { void parseSendBuyCharmRune(NetworkMessage &msg); void parseBestiarysendMonsterData(NetworkMessage &msg); void parseCyclopediaMonsterTracker(NetworkMessage &msg); - void parseObjectInfo(NetworkMessage &msg); void parseTeleport(NetworkMessage &msg); void parseThrow(NetworkMessage &msg); @@ -240,14 +270,14 @@ class ProtocolGame final : public Protocol { void sendChannel(uint16_t channelId, const std::string &channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers); void sendOpenPrivateChannel(const std::string &receiver); void sendExperienceTracker(int64_t rawExp, int64_t finalExp); - void sendToChannel(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, uint16_t channelId); - void sendPrivateMessage(std::shared_ptr<Player> speaker, SpeakClasses type, const std::string &text); + void sendToChannel(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, uint16_t channelId); + void sendPrivateMessage(const std::shared_ptr<Player> &speaker, SpeakClasses type, const std::string &text); void sendIcons(const std::unordered_set<PlayerIcon> &iconSet, const IconBakragore iconBakragore); void sendIconBakragore(const IconBakragore icon); void sendFYIBox(const std::string &message); - void openImbuementWindow(std::shared_ptr<Item> item); - void sendImbuementResult(const std::string message); + void openImbuementWindow(const std::shared_ptr<Item> &item); + void sendImbuementResult(const std::string &message); void closeImbuementWindow(); void sendItemsPrice(); @@ -255,18 +285,11 @@ class ProtocolGame final : public Protocol { // Forge System void sendForgingData(); void sendOpenForge(); - void sendForgeError(const ReturnValue returnValue); + void sendForgeError(ReturnValue returnValue); void closeForgeWindow(); void parseForgeEnter(NetworkMessage &msg); void parseForgeBrowseHistory(NetworkMessage &msg); - void sendForgeFusionItem( - uint16_t itemId, - uint8_t tier, - bool success, - uint8_t bonus, - uint8_t coreCount, - bool convergence - ); + void sendForgeResult(ForgeAction_t actionType, uint16_t leftItemId, uint8_t leftTier, uint16_t rightItemId, uint8_t rightTier, bool success, uint8_t bonus, uint8_t coreCount, bool convergence); void sendForgeHistory(uint8_t page); void sendForgeSkillStats(NetworkMessage &msg) const; @@ -276,7 +299,7 @@ class ProtocolGame final : public Protocol { void parseSendBosstiarySlots(); void parseBosstiarySlot(NetworkMessage &msg); void sendPodiumDetails(NetworkMessage &msg, const std::vector<uint16_t> &toSendMonsters, bool isBoss) const; - void sendMonsterPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackPos); + void sendMonsterPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackPos); void parseSetMonsterPodium(NetworkMessage &msg) const; void sendBosstiaryCooldownTimer(); void sendBosstiaryEntryChanged(uint32_t bossid); @@ -286,28 +309,28 @@ class ProtocolGame final : public Protocol { void sendMagicEffect(const Position &pos, uint16_t type); void removeMagicEffect(const Position &pos, uint16_t type); void sendRestingStatus(uint8_t protection); - void sendCreatureHealth(std::shared_ptr<Creature> creature); - void sendPartyCreatureUpdate(std::shared_ptr<Creature> target); - void sendPartyCreatureShield(std::shared_ptr<Creature> target); - void sendPartyCreatureSkull(std::shared_ptr<Creature> target); - void sendPartyCreatureHealth(std::shared_ptr<Creature> target, uint8_t healthPercent); - void sendPartyPlayerMana(std::shared_ptr<Player> target, uint8_t manaPercent); - void sendPartyCreatureShowStatus(std::shared_ptr<Creature> target, bool showStatus); - void sendPartyPlayerVocation(std::shared_ptr<Player> target); - void sendPlayerVocation(std::shared_ptr<Player> target); + void sendCreatureHealth(const std::shared_ptr<Creature> &creature); + void sendPartyCreatureUpdate(const std::shared_ptr<Creature> &target); + void sendPartyCreatureShield(const std::shared_ptr<Creature> &target); + void sendPartyCreatureSkull(const std::shared_ptr<Creature> &target); + void sendPartyCreatureHealth(const std::shared_ptr<Creature> &target, uint8_t healthPercent); + void sendPartyPlayerMana(const std::shared_ptr<Player> &target, uint8_t manaPercent); + void sendPartyCreatureShowStatus(const std::shared_ptr<Creature> &target, bool showStatus); + void sendPartyPlayerVocation(const std::shared_ptr<Player> &target); + void sendPlayerVocation(const std::shared_ptr<Player> &target); void sendSkills(); void sendPing(); void sendPingBack(); - void sendCreatureTurn(std::shared_ptr<Creature> creature, uint32_t stackpos); - void sendCreatureSay(std::shared_ptr<Creature> creature, SpeakClasses type, const std::string &text, const Position* pos = nullptr); + void sendCreatureTurn(const std::shared_ptr<Creature> &creature, uint32_t stackpos); + void sendCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text, const Position* pos = nullptr); // Unjust Panel void sendUnjustifiedPoints(const uint8_t &dayProgress, const uint8_t &dayLeft, const uint8_t &weekProgress, const uint8_t &weekLeft, const uint8_t &monthProgress, const uint8_t &monthLeft, const uint8_t &skullDuration); void sendCancelWalk(); - void sendChangeSpeed(std::shared_ptr<Creature> creature, uint16_t speed); + void sendChangeSpeed(const std::shared_ptr<Creature> &creature, uint16_t speed); void sendCancelTarget(); - void sendCreatureOutfit(std::shared_ptr<Creature> creature, const Outfit_t &outfit); + void sendCreatureOutfit(const std::shared_ptr<Creature> &creature, const Outfit_t &outfit); void sendStats(); void sendBasicData(); void sendTextMessage(const TextMessage &message); @@ -322,7 +345,7 @@ class ProtocolGame final : public Protocol { void sendCyclopediaCharacterCombatStats(); void sendCyclopediaCharacterRecentDeaths(uint16_t page, uint16_t pages, const std::vector<RecentDeathEntry> &entries); void sendCyclopediaCharacterRecentPvPKills(uint16_t page, uint16_t pages, const std::vector<RecentPvPKillEntry> &entries); - void sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, std::vector<std::pair<Achievement, uint32_t>> achievementsUnlocked); + void sendCyclopediaCharacterAchievements(uint16_t secretsUnlocked, const std::vector<std::pair<Achievement, uint32_t>> &achievementsUnlocked); void sendCyclopediaCharacterItemSummary(const ItemsTierCountList &inventoryItems, const ItemsTierCountList &storeInboxItems, const StashItemList &supplyStashItems, const ItemsTierCountList &depotBoxItems, const ItemsTierCountList &inboxItems); void sendCyclopediaCharacterOutfitsMounts(); void sendCyclopediaCharacterStoreSummary(); @@ -330,13 +353,13 @@ class ProtocolGame final : public Protocol { void sendCyclopediaCharacterBadges(); void sendCyclopediaCharacterTitles(); - void sendCreatureWalkthrough(std::shared_ptr<Creature> creature, bool walkthrough); - void sendCreatureShield(std::shared_ptr<Creature> creature); - void sendCreatureEmblem(std::shared_ptr<Creature> creature); - void sendCreatureSkull(std::shared_ptr<Creature> creature); - void sendCreatureType(std::shared_ptr<Creature> creature, uint8_t creatureType); + void sendCreatureWalkthrough(const std::shared_ptr<Creature> &creature, bool walkthrough); + void sendCreatureShield(const std::shared_ptr<Creature> &creature); + void sendCreatureEmblem(const std::shared_ptr<Creature> &creature); + void sendCreatureSkull(const std::shared_ptr<Creature> &creature); + void sendCreatureType(const std::shared_ptr<Creature> &creature, uint8_t creatureType); - void sendShop(std::shared_ptr<Npc> npc); + void sendShop(const std::shared_ptr<Npc> &npc); void sendCloseShop(); void sendClientCheck(); void sendGameNews(); @@ -352,15 +375,15 @@ class ProtocolGame final : public Protocol { void sendMarketCancelOffer(const MarketOfferEx &offer); void sendMarketBrowseOwnHistory(const HistoryMarketOfferList &buyOffers, const HistoryMarketOfferList &sellOffers); void sendMarketDetail(uint16_t itemId, uint8_t tier); - void sendTradeItemRequest(const std::string &traderName, std::shared_ptr<Item> item, bool ack); + void sendTradeItemRequest(const std::string &traderName, const std::shared_ptr<Item> &item, bool ack); void sendCloseTrade(); - void updatePartyTrackerAnalyzer(const std::shared_ptr<Party> party); + void updatePartyTrackerAnalyzer(const std::shared_ptr<Party> &party); void sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string &text); - void sendTextWindow(uint32_t windowTextId, std::shared_ptr<Item> item, uint16_t maxlen, bool canWrite); + void sendTextWindow(uint32_t windowTextId, const std::shared_ptr<Item> &item, uint16_t maxlen, bool canWrite); void sendHouseWindow(uint32_t windowTextId, const std::string &text); void sendOutfitWindow(); - void sendPodiumWindow(std::shared_ptr<Item> podium, const Position &position, uint16_t itemId, uint8_t stackpos); + void sendPodiumWindow(const std::shared_ptr<Item> &podium, const Position &position, uint16_t itemId, uint8_t stackpos); void sendUpdatedVIPStatus(uint32_t guid, VipStatus_t newStatus); void sendVIP(uint32_t guid, const std::string &name, const std::string &description, uint32_t icon, bool notify, VipStatus_t status); @@ -371,13 +394,13 @@ class ProtocolGame final : public Protocol { void sendFightModes(); - void sendCreatureLight(std::shared_ptr<Creature> creature); - void sendCreatureIcon(std::shared_ptr<Creature> creature); - void sendUpdateCreature(std::shared_ptr<Creature> creature); + void sendCreatureLight(const std::shared_ptr<Creature> &creature); + void sendCreatureIcon(const std::shared_ptr<Creature> &creature); + void sendUpdateCreature(const std::shared_ptr<Creature> &creature); void sendWorldLight(const LightInfo &lightInfo); void sendTibiaTime(int32_t time); - void sendCreatureSquare(std::shared_ptr<Creature> creature, SquareColor_t color); + void sendCreatureSquare(const std::shared_ptr<Creature> &creature, SquareColor_t color); void sendSpellCooldown(uint16_t spellId, uint32_t time); void sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time); @@ -392,46 +415,46 @@ class ProtocolGame final : public Protocol { // tiles void sendMapDescription(const Position &pos); - void sendAddTileItem(const Position &pos, uint32_t stackpos, std::shared_ptr<Item> item); - void sendUpdateTileItem(const Position &pos, uint32_t stackpos, std::shared_ptr<Item> item); + void sendAddTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr<Item> &item); + void sendUpdateTileItem(const Position &pos, uint32_t stackpos, const std::shared_ptr<Item> &item); void sendRemoveTileThing(const Position &pos, uint32_t stackpos); - void sendUpdateTileCreature(const Position &pos, uint32_t stackpos, const std::shared_ptr<Creature> creature); - void sendUpdateTile(std::shared_ptr<Tile> tile, const Position &pos); + void sendUpdateTileCreature(const Position &pos, uint32_t stackpos, const std::shared_ptr<Creature> &creature); + void sendUpdateTile(const std::shared_ptr<Tile> &tile, const Position &pos); - void sendAddCreature(std::shared_ptr<Creature> creature, const Position &pos, int32_t stackpos, bool isLogin); - void sendMoveCreature(std::shared_ptr<Creature> creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport); + void sendAddCreature(const std::shared_ptr<Creature> &creature, const Position &pos, int32_t stackpos, bool isLogin); + void sendMoveCreature(const std::shared_ptr<Creature> &creature, const Position &newPos, int32_t newStackPos, const Position &oldPos, int32_t oldStackPos, bool teleport); // containers - void sendAddContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> item); - void sendUpdateContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> item); - void sendRemoveContainerItem(uint8_t cid, uint16_t slot, std::shared_ptr<Item> lastItem); + void sendAddContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &item); + void sendUpdateContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &item); + void sendRemoveContainerItem(uint8_t cid, uint16_t slot, const std::shared_ptr<Item> &lastItem); - void sendContainer(uint8_t cid, std::shared_ptr<Container> container, bool hasParent, uint16_t firstIndex); + void sendContainer(uint8_t cid, const std::shared_ptr<Container> &container, bool hasParent, uint16_t firstIndex); void sendCloseContainer(uint8_t cid); // quickloot void sendLootContainers(); - void sendLootStats(std::shared_ptr<Item> item, uint8_t count); + void sendLootStats(const std::shared_ptr<Item> &item, uint8_t count); // inventory - void sendInventoryItem(Slots_t slot, std::shared_ptr<Item> item); + void sendInventoryItem(Slots_t slot, const std::shared_ptr<Item> &item); void sendInventoryIds(); // messages void sendModalWindow(const ModalWindow &modalWindow); // analyzers - void sendKillTrackerUpdate(std::shared_ptr<Container> corpse, const std::string &name, const Outfit_t creatureOutfit); - void sendUpdateSupplyTracker(std::shared_ptr<Item> item); + void sendKillTrackerUpdate(const std::shared_ptr<Container> &corpse, const std::string &name, Outfit_t creatureOutfit); + void sendUpdateSupplyTracker(const std::shared_ptr<Item> &item); void sendUpdateImpactTracker(CombatType_t type, int32_t amount); - void sendUpdateInputAnalyzer(CombatType_t type, int32_t amount, std::string target); + void sendUpdateInputAnalyzer(CombatType_t type, int32_t amount, const std::string &target); // Hotkey equip/dequip item void parseHotkeyEquip(NetworkMessage &msg); // Help functions // translate a tile to clientreadable format - void GetTileDescription(std::shared_ptr<Tile> tile, NetworkMessage &msg); + void GetTileDescription(const std::shared_ptr<Tile> &tile, NetworkMessage &msg); // translate a floor to clientreadable format void GetFloorDescription(NetworkMessage &msg, int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, int32_t offset, int32_t &skip); @@ -439,23 +462,26 @@ class ProtocolGame final : public Protocol { // translate a map area to clientreadable format void GetMapDescription(int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, NetworkMessage &msg); - void AddCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, bool known, uint32_t remove); + void AddCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, bool known, uint32_t remove); void AddPlayerStats(NetworkMessage &msg); void AddOutfit(NetworkMessage &msg, const Outfit_t &outfit, bool addMount = true); void AddPlayerSkills(NetworkMessage &msg); + // Blessing + void sendBlessingWindow(); void sendBlessStatus(); + // End Blessing void sendPremiumTrigger(); void sendMessageDialog(const std::string &message); void AddWorldLight(NetworkMessage &msg, LightInfo lightInfo); - void AddCreatureLight(NetworkMessage &msg, std::shared_ptr<Creature> creature); + void AddCreatureLight(NetworkMessage &msg, const std::shared_ptr<Creature> &creature); // tiles static void RemoveTileThing(NetworkMessage &msg, const Position &pos, uint32_t stackpos); void sendTaskHuntingData(const std::unique_ptr<TaskHuntingSlot> &slot); - void MoveUpCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, const Position &newPos, const Position &oldPos); - void MoveDownCreature(NetworkMessage &msg, std::shared_ptr<Creature> creature, const Position &newPos, const Position &oldPos); + void MoveUpCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, const Position &newPos, const Position &oldPos); + void MoveDownCreature(NetworkMessage &msg, const std::shared_ptr<Creature> &creature, const Position &newPos, const Position &oldPos); // shop void AddHiddenShopItem(NetworkMessage &msg); @@ -468,12 +494,12 @@ class ProtocolGame final : public Protocol { void sendFeatures(); void parseInventoryImbuements(NetworkMessage &msg); - void sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> items); + void sendInventoryImbuements(const std::map<Slots_t, std::shared_ptr<Item>> &items); // reloadCreature - void reloadCreature(std::shared_ptr<Creature> creature); + void reloadCreature(const std::shared_ptr<Creature> &creature); - void getForgeInfoMap(std::shared_ptr<Item> item, std::map<uint16_t, std::map<uint8_t, uint16_t>> &itemsMap) const; + void getForgeInfoMap(const std::shared_ptr<Item> &item, std::map<uint16_t, std::map<uint8_t, uint16_t>> &itemsMap) const; // Wheel void parseOpenWheel(NetworkMessage &msg); @@ -506,13 +532,12 @@ class ProtocolGame final : public Protocol { uint16_t otclientV8 = 0; bool isOTC = false; - void sendInventory(); void sendOpenStash(); void parseStashWithdraw(NetworkMessage &msg); void sendSpecialContainersAvailable(); void addBless(); void parsePacketDead(uint8_t recvbyte); - void addCreatureIcon(NetworkMessage &msg, std::shared_ptr<Creature> creature); + void addCreatureIcon(NetworkMessage &msg, const std::shared_ptr<Creature> &creature); void sendSingleSoundEffect(const Position &pos, SoundEffect_t id, SourceEffect_t source); void sendDoubleSoundEffect(const Position &pos, SoundEffect_t mainSoundId, SourceEffect_t mainSource, SoundEffect_t secondarySoundId, SourceEffect_t secondarySource); diff --git a/src/server/network/protocol/protocollogin.cpp b/src/server/network/protocol/protocollogin.cpp index f182f957cdb..9e28982e91f 100644 --- a/src/server/network/protocol/protocollogin.cpp +++ b/src/server/network/protocol/protocollogin.cpp @@ -8,6 +8,8 @@ */ #include "server/network/protocol/protocollogin.hpp" + +#include "config/configmanager.hpp" #include "server/network/message/outputmessage.hpp" #include "game/scheduling/dispatcher.hpp" #include "account/account.hpp" @@ -17,8 +19,8 @@ #include "core.hpp" #include "enums/account_errors.hpp" -void ProtocolLogin::disconnectClient(const std::string &message) { - auto output = OutputMessagePool::getOutputMessage(); +void ProtocolLogin::disconnectClient(const std::string &message) const { + const auto output = OutputMessagePool::getOutputMessage(); output->addByte(0x0B); output->addString(message); @@ -27,7 +29,7 @@ void ProtocolLogin::disconnectClient(const std::string &message) { disconnect(); } -void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const std::string &password) { +void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const std::string &password) const { Account account(accountDescriptor); account.setProtocolCompat(oldProtocol); @@ -39,7 +41,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const return; } - if (account.load() != enumToValue(AccountErrors_t::Ok) || !account.authenticate(password)) { + if (account.load() != AccountErrors_t::Ok || !account.authenticate(password)) { std::ostringstream ss; ss << (oldProtocol ? "Username" : "Email") << " or password is not correct."; disconnectClient(ss.str()); @@ -64,7 +66,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const // Add char list auto [players, result] = account.getAccountPlayers(); - if (enumToValue(AccountErrors_t::Ok) != result) { + if (AccountErrors_t::Ok != result) { g_logger().warn("Account[{}] failed to load players!", account.getID()); } @@ -105,7 +107,7 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage &msg) { msg.skipBytes(2); // client OS - uint16_t version = msg.get<uint16_t>(); + auto version = msg.get<uint16_t>(); // Old protocol support oldProtocol = version == 1100; diff --git a/src/server/network/protocol/protocollogin.hpp b/src/server/network/protocol/protocollogin.hpp index 6652a85625e..d3051119ba3 100644 --- a/src/server/network/protocol/protocollogin.hpp +++ b/src/server/network/protocol/protocollogin.hpp @@ -14,7 +14,7 @@ class NetworkMessage; class OutputMessage; -class ProtocolLogin : public Protocol { +class ProtocolLogin final : public Protocol { public: // static protocol information enum { SERVER_SENDS_FIRST = false }; @@ -24,15 +24,15 @@ class ProtocolLogin : public Protocol { return "login protocol"; } - explicit ProtocolLogin(Connection_ptr loginConnection) : + explicit ProtocolLogin(const Connection_ptr &loginConnection) : Protocol(loginConnection) { } - void onRecvFirstMessage(NetworkMessage &msg); + void onRecvFirstMessage(NetworkMessage &msg) override; private: - void disconnectClient(const std::string &message); + void disconnectClient(const std::string &message) const; - void getCharacterList(const std::string &accountDescriptor, const std::string &password); + void getCharacterList(const std::string &accountDescriptor, const std::string &password) const; bool oldProtocol = false; }; diff --git a/src/server/network/protocol/protocolstatus.cpp b/src/server/network/protocol/protocolstatus.cpp index bed5fd7a9bd..fd2bd2968aa 100644 --- a/src/server/network/protocol/protocolstatus.cpp +++ b/src/server/network/protocol/protocolstatus.cpp @@ -7,11 +7,11 @@ * Website: https://docs.opentibiabr.com/ */ -#include "core.hpp" - #include "server/network/protocol/protocolstatus.hpp" #include "config/configmanager.hpp" +#include "core.hpp" +#include "creatures/players/player.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "server/network/message/outputmessage.hpp" @@ -24,11 +24,11 @@ std::map<uint32_t, int64_t> ProtocolStatus::ipConnectMap; const uint64_t ProtocolStatus::start = OTSYS_TIME(true); void ProtocolStatus::onRecvFirstMessage(NetworkMessage &msg) { - uint32_t ip = getIP(); + const uint32_t ip = getIP(); if (ip != 0x0100007F) { - std::string ipStr = convertIPToString(ip); + const std::string ipStr = convertIPToString(ip); if (ipStr != g_configManager().getString(IP)) { - std::map<uint32_t, int64_t>::const_iterator it = ipConnectMap.find(ip); + const auto it = ipConnectMap.find(ip); if (it != ipConnectMap.end() && (OTSYS_TIME() < (it->second + g_configManager().getNumber(STATUSQUERY_TIMEOUT)))) { disconnect(); return; @@ -55,7 +55,7 @@ void ProtocolStatus::onRecvFirstMessage(NetworkMessage &msg) { // Another ServerInfo protocol case 0x01: { - uint16_t requestedInfo = msg.get<uint16_t>(); // only a Byte is necessary, though we could add new info here + auto requestedInfo = msg.get<uint16_t>(); // only a Byte is necessary, though we could add new info here std::string characterName; if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { characterName = msg.getString(); @@ -77,7 +77,7 @@ void ProtocolStatus::onRecvFirstMessage(NetworkMessage &msg) { } void ProtocolStatus::sendStatusString() { - auto output = OutputMessagePool::getOutputMessage(); + const auto output = OutputMessagePool::getOutputMessage(); setRawMessages(true); @@ -90,7 +90,7 @@ void ProtocolStatus::sendStatusString() { tsqp.append_attribute("version") = "1.0"; pugi::xml_node serverinfo = tsqp.append_child("serverinfo"); - uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; + const uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; serverinfo.append_attribute("uptime") = std::to_string(uptime).c_str(); serverinfo.append_attribute("ip") = g_configManager().getString(IP).c_str(); serverinfo.append_attribute("servername") = g_configManager().getString(ConfigKey_t::SERVER_NAME).c_str(); @@ -154,14 +154,14 @@ void ProtocolStatus::sendStatusString() { std::ostringstream ss; doc.save(ss, "", pugi::format_raw); - std::string data = ss.str(); + const std::string data = ss.str(); output->addBytes(data.c_str(), data.size()); send(output); disconnect(); } -void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &characterName) { - auto output = OutputMessagePool::getOutputMessage(); +void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &characterName) const { + const auto output = OutputMessagePool::getOutputMessage(); if (requestedInfo & REQUEST_BASIC_SERVER_INFO) { output->addByte(0x10); diff --git a/src/server/network/protocol/protocolstatus.hpp b/src/server/network/protocol/protocolstatus.hpp index 78b03a74333..d5600438734 100644 --- a/src/server/network/protocol/protocolstatus.hpp +++ b/src/server/network/protocol/protocolstatus.hpp @@ -22,13 +22,13 @@ class ProtocolStatus final : public Protocol { return "status protocol"; } - explicit ProtocolStatus(Connection_ptr conn) : + explicit ProtocolStatus(const Connection_ptr &conn) : Protocol(conn) { } void onRecvFirstMessage(NetworkMessage &msg) override; void sendStatusString(); - void sendInfo(uint16_t requestedInfo, const std::string &characterName); + void sendInfo(uint16_t requestedInfo, const std::string &characterName) const; static const uint64_t start; diff --git a/src/server/network/webhook/webhook.cpp b/src/server/network/webhook/webhook.cpp index 6d28e263e54..006be8bbfaa 100644 --- a/src/server/network/webhook/webhook.cpp +++ b/src/server/network/webhook/webhook.cpp @@ -8,6 +8,7 @@ */ #include "server/network/webhook/webhook.hpp" + #include "config/configmanager.hpp" #include "game/scheduling/dispatcher.hpp" #include "utils/tools.hpp" @@ -23,7 +24,7 @@ Webhook::Webhook(ThreadPool &threadPool) : headers = curl_slist_append(headers, "content-type: application/json"); headers = curl_slist_append(headers, "accept: application/json"); - if (headers == NULL) { + if (headers == nullptr) { g_logger().error("Failed to init curl, appending request headers failed"); return; } @@ -42,9 +43,9 @@ void Webhook::run() { ); } -void Webhook::sendPayload(const std::string &payload, std::string url) { +void Webhook::sendPayload(const std::string &payload, const std::string &url) { std::scoped_lock lock { taskLock }; - webhooks.push_back(std::make_shared<WebhookTask>(payload, url)); + webhooks.emplace_back(std::make_shared<WebhookTask>(payload, url)); } void Webhook::sendMessage(const std::string &title, const std::string &message, int color, std::string url, bool embed) { @@ -87,7 +88,7 @@ int Webhook::sendRequest(const char* url, const char* payload, std::string* resp curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_USERAGENT, "canary (https://github.com/opentibiabr/canary)"); - CURLcode res = curl_easy_perform(curl); + const CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { g_logger().error("Failed to send webhook message with the error: {}", curl_easy_strerror(res)); @@ -105,15 +106,15 @@ int Webhook::sendRequest(const char* url, const char* payload, std::string* resp } size_t Webhook::writeCallback(void* contents, size_t size, size_t nmemb, void* userp) { - size_t real_size = size * nmemb; - auto* str = reinterpret_cast<std::string*>(userp); - str->append(reinterpret_cast<char*>(contents), real_size); + const size_t real_size = size * nmemb; + auto* str = static_cast<std::string*>(userp); + str->append(static_cast<char*>(contents), real_size); return real_size; } std::string Webhook::getPayload(const std::string &title, const std::string &message, int color, bool embed) const { - std::time_t now = getTimeNow(); - std::string time_buf = formatDate(now); + const std::time_t now = getTimeNow(); + const std::string time_buf = formatDate(now); std::stringstream footer_text; footer_text @@ -123,19 +124,19 @@ std::string Webhook::getPayload(const std::string &title, const std::string &mes std::stringstream payload; if (embed) { payload << "{ \"embeds\": [{ "; - payload << "\"title\": \"" << title << "\", "; + payload << R"("title": ")" << title << "\", "; if (!message.empty()) { - payload << "\"description\": \"" << message << "\", "; + payload << R"("description": ")" << message << "\", "; } if (g_configManager().getBoolean(DISCORD_SEND_FOOTER)) { - payload << "\"footer\": { \"text\": \"" << footer_text.str() << "\" }, "; + payload << R"("footer": { "text": ")" << footer_text.str() << "\" }, "; } if (color >= 0) { payload << "\"color\": " << color; } payload << " }] }"; } else { - payload << "{ \"content\": \"" << (!message.empty() ? message : title) << "\" }"; + payload << R"({ "content": ")" << (!message.empty() ? message : title) << "\" }"; } return payload.str(); diff --git a/src/server/network/webhook/webhook.hpp b/src/server/network/webhook/webhook.hpp index bae62a64c35..4ce989099c1 100644 --- a/src/server/network/webhook/webhook.hpp +++ b/src/server/network/webhook/webhook.hpp @@ -30,7 +30,7 @@ class Webhook { void run(); - void sendPayload(const std::string &payload, std::string url); + void sendPayload(const std::string &payload, const std::string &url); void sendMessage(const std::string &title, const std::string &message, int color, std::string url = "", bool embed = true); void sendMessage(const std::string &message, std::string url = ""); diff --git a/src/server/server.cpp b/src/server/server.cpp index 1ef5e01a06d..2ba8f36dfd0 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -7,8 +7,9 @@ * Website: https://docs.opentibiabr.com/ */ -#include "server/network/message/outputmessage.hpp" #include "server/server.hpp" + +#include "server/network/message/outputmessage.hpp" #include "config/configmanager.hpp" #include "game/scheduling/dispatcher.hpp" #include "creatures/players/management/ban.hpp" @@ -69,7 +70,7 @@ bool ServicePort::is_single_socket() const { std::string ServicePort::get_protocol_names() const { if (services.empty()) { - return std::string(); + return {}; } std::string str = services.front()->get_protocol_name(); @@ -90,15 +91,15 @@ void ServicePort::accept() { acceptor->async_accept(connection->getSocket(), [self = shared_from_this(), connection](const std::error_code &error) { self->onAccept(connection, error); }); } -void ServicePort::onAccept(Connection_ptr connection, const std::error_code &error) { +void ServicePort::onAccept(const Connection_ptr &connection, const std::error_code &error) { if (!error) { if (services.empty()) { return; } - auto remote_ip = connection->getIP(); + const auto remote_ip = connection->getIP(); if (remote_ip != 0 && inject<Ban>().acceptConnection(remote_ip)) { - Service_ptr service = services.front(); + const Service_ptr service = services.front(); if (service->is_single_socket()) { connection->accept(service->make_protocol(connection)); } else { @@ -121,7 +122,7 @@ void ServicePort::onAccept(Connection_ptr connection, const std::error_code &err } Protocol_ptr ServicePort::make_protocol(bool checksummed, NetworkMessage &msg, const Connection_ptr &connection) const { - uint8_t protocolID = msg.getByte(); + const uint8_t protocolID = msg.getByte(); for (auto &service : services) { if (protocolID != service->get_protocol_identifier()) { continue; @@ -134,12 +135,12 @@ Protocol_ptr ServicePort::make_protocol(bool checksummed, NetworkMessage &msg, c return nullptr; } -void ServicePort::onStopServer() { +void ServicePort::onStopServer() const { close(); } -void ServicePort::openAcceptor(std::weak_ptr<ServicePort> weak_service, uint16_t port) { - if (auto service = weak_service.lock()) { +void ServicePort::openAcceptor(const std::weak_ptr<ServicePort> &weak_service, uint16_t port) { + if (const auto service = weak_service.lock()) { service->open(port); } } @@ -152,9 +153,9 @@ void ServicePort::open(uint16_t port) { try { if (g_configManager().getBoolean(BIND_ONLY_GLOBAL_ADDRESS)) { - acceptor.reset(new asio::ip::tcp::acceptor(io_service, asio::ip::tcp::endpoint(asio::ip::address(asio::ip::address_v4::from_string(g_configManager().getString(IP))), serverPort))); + acceptor = std::make_unique<asio::ip::tcp::acceptor>(io_service, asio::ip::tcp::endpoint(asio::ip::address(asio::ip::address_v4::from_string(g_configManager().getString(IP))), serverPort)); } else { - acceptor.reset(new asio::ip::tcp::acceptor(io_service, asio::ip::tcp::endpoint(asio::ip::address(asio::ip::address_v4(INADDR_ANY)), serverPort))); + acceptor = std::make_unique<asio::ip::tcp::acceptor>(io_service, asio::ip::tcp::endpoint(asio::ip::address(asio::ip::address_v4(INADDR_ANY)), serverPort)); } acceptor->set_option(asio::ip::tcp::no_delay(true)); @@ -171,7 +172,7 @@ void ServicePort::open(uint16_t port) { } } -void ServicePort::close() { +void ServicePort::close() const { if (acceptor && acceptor->is_open()) { std::error_code error; acceptor->close(error); @@ -183,6 +184,6 @@ bool ServicePort::add_service(const Service_ptr &new_svc) { return false; } - services.push_back(new_svc); + services.emplace_back(new_svc); return true; } diff --git a/src/server/server.hpp b/src/server/server.hpp index dfb6aef5cf8..0a658f4d26f 100644 --- a/src/server/server.hpp +++ b/src/server/server.hpp @@ -17,6 +17,7 @@ class Protocol; class ServiceBase { public: + virtual ~ServiceBase() = default; virtual bool is_single_socket() const = 0; virtual bool is_checksummed() const = 0; virtual uint8_t get_protocol_identifier() const = 0; @@ -56,17 +57,17 @@ class ServicePort : public std::enable_shared_from_this<ServicePort> { ServicePort(const ServicePort &) = delete; ServicePort &operator=(const ServicePort &) = delete; - static void openAcceptor(std::weak_ptr<ServicePort> weak_service, uint16_t port); + static void openAcceptor(const std::weak_ptr<ServicePort> &weak_service, uint16_t port); void open(uint16_t port); - void close(); + void close() const; bool is_single_socket() const; std::string get_protocol_names() const; bool add_service(const Service_ptr &new_svc); Protocol_ptr make_protocol(bool checksummed, NetworkMessage &msg, const Connection_ptr &connection) const; - void onStopServer(); - void onAccept(Connection_ptr connection, const std::error_code &error); + void onStopServer() const; + void onAccept(const Connection_ptr &connection, const std::error_code &error); private: void accept(); @@ -120,7 +121,7 @@ bool ServiceManager::add(uint16_t port) { ServicePort_ptr service_port; - auto foundServicePort = acceptors.find(port); + const auto foundServicePort = acceptors.find(port); if (foundServicePort == acceptors.end()) { service_port = std::make_shared<ServicePort>(io_service); diff --git a/src/server/signals.cpp b/src/server/signals.cpp index e309f09ab1e..1e6e0e4ece7 100644 --- a/src/server/signals.cpp +++ b/src/server/signals.cpp @@ -7,14 +7,19 @@ * Website: https://docs.opentibiabr.com/ */ +#include "server/signals.hpp" + +#include "config/configmanager.hpp" +#include "creatures/appearance/mounts/mounts.hpp" +#include "creatures/interactions/chat.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" #include "game/scheduling/save_manager.hpp" #include "lib/thread/thread_pool.hpp" #include "lua/creature/events.hpp" -#include "lua/scripts/lua_environment.hpp" #include "lua/global/globalevent.hpp" -#include "server/signals.hpp" +#include "lua/scripts/lua_environment.hpp" +#include "lib/di/container.hpp" Signals::Signals(asio::io_service &service) : set(service) { @@ -109,7 +114,7 @@ void Signals::sighupHandler() { Item::items.reload(); g_logger().info("Reloaded items"); - g_game().mounts.reload(); + g_game().mounts->reload(); g_logger().info("Reloaded mounts"); g_events().loadFromXml(); diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 1b2ba9da7f4..d3ce8329d73 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${PROJECT_NAME}_lib PRIVATE + counter_pointer.cpp pugicast.cpp tools.cpp wildcardtree.cpp diff --git a/src/utils/arraylist.hpp b/src/utils/arraylist.hpp index da507e68480..52850929e7d 100644 --- a/src/utils/arraylist.hpp +++ b/src/utils/arraylist.hpp @@ -48,7 +48,7 @@ namespace stdext { bool erase(const T &v) { update(); - const auto &it = std::ranges::find(backContainer, v); + auto it = std::ranges::find(backContainer, v); if (it == backContainer.end()) { return false; } diff --git a/src/utils/benchmark.hpp b/src/utils/benchmark.hpp index 961547efc94..2524866a6a8 100644 --- a/src/utils/benchmark.hpp +++ b/src/utils/benchmark.hpp @@ -9,7 +9,6 @@ #pragma once -#include <ctime> #include <cstdint> #include <chrono> @@ -74,7 +73,7 @@ class Benchmark { } private: - int64_t time() const noexcept { + static int64_t time() noexcept { return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); } diff --git a/src/utils/counter_pointer.cpp b/src/utils/counter_pointer.cpp new file mode 100644 index 00000000000..cdd0b56e8af --- /dev/null +++ b/src/utils/counter_pointer.cpp @@ -0,0 +1,31 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR <opentibiabr@outlook.com> + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#include "utils/counter_pointer.hpp" + +#include "lib/di/container.hpp" +#include "lib/logging/logger.hpp" + +SharedPtrManager &SharedPtrManager::getInstance() { + static SharedPtrManager instance; + return instance; +} + +void SharedPtrManager::countAllReferencesAndClean() { + for (auto it = m_sharedPtrMap.begin(); it != m_sharedPtrMap.end();) { + const auto &sptr = it->second.lock(); + if (sptr) { + g_logger().debug("Counting references of shared_ptr ({}): {}", it->first, sptr.use_count()); + ++it; + } else { + g_logger().debug("Object {} was destroyed and will be removed from the map.", it->first); + it = m_sharedPtrMap.erase(it); + } + } +} diff --git a/src/utils/counter_pointer.hpp b/src/utils/counter_pointer.hpp new file mode 100644 index 00000000000..15e2b56ef53 --- /dev/null +++ b/src/utils/counter_pointer.hpp @@ -0,0 +1,34 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR <opentibiabr@outlook.com> + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +class SharedPtrManager { +public: + SharedPtrManager() = default; + ~SharedPtrManager() = default; + + // Singleton - ensures we don't accidentally copy it. + SharedPtrManager(const SharedPtrManager &) = delete; + SharedPtrManager &operator=(const SharedPtrManager &) = delete; + + static SharedPtrManager &getInstance(); + + template <typename T> + void store(const std::string &name, const std::shared_ptr<T> &ptr) { + m_sharedPtrMap[name] = ptr; + } + + void countAllReferencesAndClean(); + +private: + std::unordered_map<std::string, std::weak_ptr<void>> m_sharedPtrMap; +}; + +constexpr auto g_counterPointer = SharedPtrManager::getInstance; diff --git a/src/utils/definitions.hpp b/src/utils/definitions.hpp index d557896f361..24a6b7d134b 100644 --- a/src/utils/definitions.hpp +++ b/src/utils/definitions.hpp @@ -13,6 +13,8 @@ #define __FUNCTION__ __func__ #endif +#define __METRICS_METHOD_NAME__ std::source_location::current().function_name() + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif diff --git a/src/utils/hash.hpp b/src/utils/hash.hpp index 6b819c9bb7d..7acee5551e7 100644 --- a/src/utils/hash.hpp +++ b/src/utils/hash.hpp @@ -1,8 +1,8 @@ #pragma once namespace stdext { - template <class _Kty> - using hash = phmap::Hash<_Kty>; + template <class Kty> + using hash = phmap::Hash<Kty>; // Robin Hood lib inline size_t hash_int(uint64_t x) noexcept { @@ -17,19 +17,19 @@ namespace stdext { seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2); } - void hash_combine(size_t &seed, uint64_t v) { + inline void hash_combine(size_t &seed, uint64_t v) { hash_union(seed, hash_int(v)); } - void hash_combine(size_t &seed, uint32_t v) { + inline void hash_combine(size_t &seed, uint32_t v) { hash_union(seed, hash_int(v)); } - void hash_combine(size_t &seed, uint16_t v) { + inline void hash_combine(size_t &seed, uint16_t v) { hash_union(seed, hash_int(v)); } - void hash_combine(size_t &seed, uint8_t v) { + inline void hash_combine(size_t &seed, uint8_t v) { hash_union(seed, hash_int(v)); } diff --git a/src/utils/pugicast.hpp b/src/utils/pugicast.hpp index d09532a2d5c..91043596605 100644 --- a/src/utils/pugicast.hpp +++ b/src/utils/pugicast.hpp @@ -19,7 +19,7 @@ namespace pugi { T value; // Set the last character to parse - std::string_view string(str); + const std::string_view string(str); const auto last = str + string.size(); // Convert the string to the specified type @@ -38,14 +38,12 @@ namespace pugi { // If the string could not be parsed as the specified type if (errorCode == std::errc::invalid_argument) { // Throw an exception indicating that the argument is invalid - logError(fmt::format("Invalid argument {}", str)); - throw std::invalid_argument("Invalid argument: " + std::string(str)); + logError(fmt::format("[{}] Invalid argument {}", __FUNCTION__, str)); } // If the parsed value is out of range for the specified type else if (errorCode == std::errc::result_out_of_range) { // Throw an exception indicating that the result is out of range - logError(fmt::format("Result out of range: {}", str)); - throw std::out_of_range("Result out of range: " + std::string(str)); + logError(fmt::format("[{}] Result out of range: {}", __FUNCTION__, str)); } // Return a default value if no exception is thrown diff --git a/src/utils/simd.hpp b/src/utils/simd.hpp index 7e57e75bfad..f1116f1ce86 100644 --- a/src/utils/simd.hpp +++ b/src/utils/simd.hpp @@ -56,11 +56,11 @@ #ifdef _MSC_VER #include <intrin.h> -__forceinline unsigned int _mm_ctz(unsigned int value) { +__forceinline unsigned int mm_ctz(unsigned int value) { unsigned long i = 0; _BitScanForward(&i, value); return static_cast<unsigned int>(i); } #else - #define _mm_ctz __builtin_ctz + #define mm_ctz __builtin_ctz #endif diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp index 0037651f21c..57c9c873282 100644 --- a/src/utils/tools.cpp +++ b/src/utils/tools.cpp @@ -10,8 +10,14 @@ #include "utils/tools.hpp" #include "core.hpp" -#include "items/item.hpp" #include "enums/object_category.hpp" +#include "items/item.hpp" +#include "lua/lua_definitions.hpp" +#include "utils/const.hpp" +#include "config/configmanager.hpp" + +#include "absl/debugging/stacktrace.h" +#include "absl/debugging/symbolize.h" void printXMLError(const std::string &where, const std::string &fileName, const pugi::xml_parse_result &result) { g_logger().error("[{}] Failed to load {}: {}", where, fileName, result.description()); @@ -25,14 +31,14 @@ void printXMLError(const std::string &where, const std::string &fileName, const uint32_t currentLine = 1; std::string line; - size_t offset = static_cast<size_t>(result.offset); + const auto offset = static_cast<size_t>(result.offset); size_t lineOffsetPosition = 0; size_t index = 0; size_t bytes; do { bytes = fread(buffer, 1, 32768, file); for (size_t i = 0; i < bytes; ++i) { - char ch = buffer[i]; + const char ch = buffer[i]; if (ch == '\n') { if ((index + i) >= offset) { lineOffsetPosition = line.length() - ((index + i) - offset); @@ -135,7 +141,7 @@ std::string transformToSHA1(const std::string &input) { uint32_t length_low = 0; uint32_t length_high = 0; - for (char ch : input) { + for (const char ch : input) { messageBlock[index++] = ch; length_low += 8; @@ -177,7 +183,7 @@ std::string transformToSHA1(const std::string &input) { processSHA1MessageBlock(messageBlock, H); char hexstring[41]; - static const char hexDigits[] = { "0123456789abcdef" }; + static constexpr char hexDigits[] = { "0123456789abcdef" }; for (int hashByte = 20; --hashByte >= 0;) { const uint8_t byte = H[hashByte >> 2] >> (((3 - hashByte) & 3) << 3); index = hashByte << 1; @@ -189,8 +195,8 @@ std::string transformToSHA1(const std::string &input) { uint16_t getStashSize(const std::map<uint16_t, uint32_t> &itemList) { uint16_t size = 0; - for (auto item : itemList) { - size += ceil(item.second / (float_t)Item::items[item.first].stackSize); + for (const auto &[itemId, itemCount] : itemList) { + size += ceil(itemCount / static_cast<float_t>(Item::items[itemId].stackSize)); } return size; } @@ -226,14 +232,14 @@ std::string generateToken(const std::string &key, uint32_t ticks) { message.assign(transformToSHA1(oKeyPad)); // calculate hmac offset - uint32_t offset = static_cast<uint32_t>(std::stol(message.substr(39, 1), nullptr, 16) & 0xF); + const auto offset = static_cast<uint32_t>(std::stol(message.substr(39, 1), nullptr, 16) & 0xF); // get truncated hash - uint32_t truncHash = std::stol(message.substr(2 * offset, 8), nullptr, 16) & 0x7FFFFFFF; + const uint32_t truncHash = std::stol(message.substr(2 * offset, 8), nullptr, 16) & 0x7FFFFFFF; message.assign(std::to_string(truncHash)); // return only last AUTHENTICATOR_DIGITS (default 6) digits, also asserts exactly 6 digits - uint32_t hashLen = message.length(); + const uint32_t hashLen = message.length(); message.assign(message.substr(hashLen - std::min(hashLen, AUTHENTICATOR_DIGITS))); message.insert(0, AUTHENTICATOR_DIGITS - std::min(hashLen, AUTHENTICATOR_DIGITS), '0'); return message; @@ -258,7 +264,7 @@ void trim_left(std::string &source, char t) { } std::string keepFirstWordOnly(std::string &str) { - size_t spacePos = str.find(' '); + const size_t spacePos = str.find(' '); if (spacePos != std::string::npos) { str.erase(spacePos); } @@ -267,7 +273,7 @@ std::string keepFirstWordOnly(std::string &str) { } void toLowerCaseString(std::string &source) { - std::transform(source.begin(), source.end(), source.begin(), tolower); + std::ranges::transform(source, source.begin(), tolower); } std::string asLowerCaseString(std::string source) { @@ -276,7 +282,7 @@ std::string asLowerCaseString(std::string source) { } std::string asUpperCaseString(std::string source) { - std::transform(source.begin(), source.end(), source.begin(), toupper); + std::ranges::transform(source, source.begin(), toupper); return source; } @@ -284,7 +290,7 @@ std::string toCamelCase(const std::string &str) { std::string result; bool capitalizeNext = false; - for (char ch : str) { + for (const char ch : str) { if (ch == '_' || std::isspace(ch) || ch == '-') { capitalizeNext = true; } else { @@ -304,7 +310,7 @@ std::string toPascalCase(const std::string &str) { std::string result; bool capitalizeNext = true; - for (char ch : str) { + for (const char ch : str) { if (ch == '_' || std::isspace(ch) || ch == '-') { capitalizeNext = true; } else { @@ -322,7 +328,7 @@ std::string toPascalCase(const std::string &str) { std::string toSnakeCase(const std::string &str) { std::string result; - for (char ch : str) { + for (const char ch : str) { if (std::isupper(ch)) { result += '_'; result += std::tolower(ch); @@ -338,7 +344,7 @@ std::string toSnakeCase(const std::string &str) { std::string toKebabCase(const std::string &str) { std::string result; - for (char ch : str) { + for (const char ch : str) { if (std::isupper(ch)) { result += '-'; result += std::tolower(ch); @@ -355,7 +361,7 @@ std::string toKebabCase(const std::string &str) { std::string toStartCaseWithSpace(const std::string &str) { std::string result; for (size_t i = 0; i < str.length(); ++i) { - char ch = str[i]; + const char ch = str[i]; if (i == 0 || std::isupper(ch)) { if (i > 0) { result += ' '; @@ -399,7 +405,8 @@ int32_t uniform_random(int32_t minNumber, int32_t maxNumber) { static std::uniform_int_distribution<int32_t> uniformRand; if (minNumber == maxNumber) { return minNumber; - } else if (minNumber > maxNumber) { + } + if (minNumber > maxNumber) { std::swap(minNumber, maxNumber); } return uniformRand(getRandomGenerator(), std::uniform_int_distribution<int32_t>::param_type(minNumber, maxNumber)); @@ -427,9 +434,12 @@ void trimString(std::string &str) { } std::string convertIPToString(uint32_t ip) { - char buffer[17]; - fmt::format_to_n(buffer, sizeof(buffer), "{}.{}.{}.{}", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24)); - return buffer; + std::array<char, 16> buffer; + auto result = fmt::format_to_n(buffer.data(), buffer.size() - 1, "{}.{}.{}.{}", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24)); + + buffer[std::min(result.size, buffer.size() - 1)] = '\0'; + + return std::string(buffer.data()); } std::string formatDate(time_t time) { @@ -461,8 +471,8 @@ std::string formatTime(time_t time) { std::string formatEnumName(std::string_view name) { std::string result { name.begin(), name.end() }; - std::replace(result.begin(), result.end(), '_', ' '); - std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::tolower(c); }); + std::ranges::replace(result, '_', ' '); + std::ranges::transform(result, result.begin(), [](unsigned char c) { return std::tolower(c); }); return result; } @@ -471,19 +481,20 @@ std::time_t getTimeNow() { } int64_t getTimeMsNow() { - auto duration = std::chrono::system_clock::now().time_since_epoch(); + const auto duration = std::chrono::system_clock::now().time_since_epoch(); return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); } int64_t getTimeUsNow() { - auto duration = std::chrono::system_clock::now().time_since_epoch(); + const auto duration = std::chrono::system_clock::now().time_since_epoch(); return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); } BedItemPart_t getBedPart(const std::string_view string) { if (string == "pillow" || string == "1") { return BED_PILLOW_PART; - } else if (string == "blanket" || string == "2") { + } + if (string == "blanket" || string == "2") { return BED_BLANKET_PART; } return BED_NONE_PART; @@ -559,12 +570,12 @@ Position getNextPosition(Direction direction, Position pos) { } Direction getDirectionTo(const Position &from, const Position &to, bool exactDiagonalOnly /* =true*/) { - int_fast32_t dx = Position::getOffsetX(from, to); - int_fast32_t dy = Position::getOffsetY(from, to); + const int_fast32_t dx = Position::getOffsetX(from, to); + const int_fast32_t dy = Position::getOffsetY(from, to); if (exactDiagonalOnly) { - int_fast32_t absDx = std::abs(dx); - int_fast32_t absDy = std::abs(dy); + const int_fast32_t absDx = std::abs(dx); + const int_fast32_t absDy = std::abs(dy); /* * Only consider diagonal if dx and dy are equal (exact diagonal). @@ -885,7 +896,7 @@ SpawnTypeNames spawnTypeNames = { }; MagicEffectClasses getMagicEffect(const std::string &strValue) { - auto magicEffect = magicEffectNames.find(strValue); + const auto magicEffect = magicEffectNames.find(strValue); if (magicEffect != magicEffectNames.end()) { return magicEffect->second; } @@ -893,7 +904,7 @@ MagicEffectClasses getMagicEffect(const std::string &strValue) { } ShootType_t getShootType(const std::string &strValue) { - auto shootType = shootTypeNames.find(strValue); + const auto shootType = shootTypeNames.find(strValue); if (shootType != shootTypeNames.end()) { return shootType->second; } @@ -901,7 +912,7 @@ ShootType_t getShootType(const std::string &strValue) { } Ammo_t getAmmoType(const std::string &strValue) { - auto ammoType = ammoTypeNames.find(strValue); + const auto ammoType = ammoTypeNames.find(strValue); if (ammoType != ammoTypeNames.end()) { return ammoType->second; } @@ -909,7 +920,7 @@ Ammo_t getAmmoType(const std::string &strValue) { } WeaponAction_t getWeaponAction(const std::string &strValue) { - auto weaponAction = weaponActionNames.find(strValue); + const auto weaponAction = weaponActionNames.find(strValue); if (weaponAction != weaponActionNames.end()) { return weaponAction->second; } @@ -917,7 +928,7 @@ WeaponAction_t getWeaponAction(const std::string &strValue) { } Skulls_t getSkullType(const std::string &strValue) { - auto skullType = skullNames.find(strValue); + const auto skullType = skullNames.find(strValue); if (skullType != skullNames.end()) { return skullType->second; } @@ -925,7 +936,7 @@ Skulls_t getSkullType(const std::string &strValue) { } ImbuementTypes_t getImbuementType(const std::string &strValue) { - auto imbuementType = imbuementTypeNames.find(strValue); + const auto imbuementType = imbuementTypeNames.find(strValue); if (imbuementType != imbuementTypeNames.end()) { return imbuementType->second; } @@ -937,7 +948,7 @@ ImbuementTypes_t getImbuementType(const std::string &strValue) { * It will be dropped with monsters. Use RespawnPeriod_t instead. */ SpawnType_t getSpawnType(const std::string &strValue) { - auto spawnType = spawnTypeNames.find(strValue); + const auto spawnType = spawnTypeNames.find(strValue); if (spawnType != spawnTypeNames.end()) { return spawnType->second; } @@ -1001,7 +1012,7 @@ uint32_t adlerChecksum(const uint8_t* data, size_t length) { return 0; } - const uint16_t adler = 65521; + constexpr uint16_t adler = 65521; uint32_t a = 1, b = 0; @@ -1032,7 +1043,7 @@ std::string ucfirst(std::string str) { } std::string ucwords(std::string str) { - size_t strLength = str.length(); + const size_t strLength = str.length(); if (strLength == 0) { return str; } @@ -1052,7 +1063,7 @@ bool booleanString(const std::string &str) { return false; } - char ch = tolower(str.front()); + const char ch = tolower(str.front()); return ch != 'f' && ch != 'n' && ch != '0'; } @@ -1073,7 +1084,7 @@ std::string getWeaponName(WeaponType_t weaponType) { case WEAPON_MISSILE: return "missile"; default: - return std::string(); + return {}; } } @@ -1090,7 +1101,7 @@ WeaponType_t getWeaponType(const std::string &name) { { "missile", WeaponType_t::WEAPON_MISSILE } }; - auto it = type_mapping.find(name); + const auto it = type_mapping.find(name); if (it != type_mapping.end()) { return it->second; } @@ -1110,7 +1121,7 @@ MoveEvent_t getMoveEventType(const std::string &name) { { "removeitemitemtile", MOVE_EVENT_REMOVE_ITEM_ITEMTILE } }; - auto it = move_event_type_mapping.find(name); + const auto it = move_event_type_mapping.find(name); if (it != move_event_type_mapping.end()) { return it->second; } @@ -1119,7 +1130,7 @@ MoveEvent_t getMoveEventType(const std::string &name) { } std::string getCombatName(CombatType_t combatType) { - auto combatName = combatTypeNames.find(combatType); + const auto combatName = combatTypeNames.find(combatType); if (combatName != combatTypeNames.end()) { return combatName->second; } @@ -1127,19 +1138,19 @@ std::string getCombatName(CombatType_t combatType) { } CombatType_t getCombatTypeByName(const std::string &combatname) { - auto it = std::find_if(combatTypeNames.begin(), combatTypeNames.end(), [combatname](const std::pair<CombatType_t, std::string> &pair) { + const auto it = std::ranges::find_if(combatTypeNames, [&combatname](const std::pair<CombatType_t, std::string> &pair) { return pair.second == combatname; }); return it != combatTypeNames.end() ? it->first : COMBAT_NONE; } -size_t combatTypeToIndex(CombatType_t combatType) { - auto enum_index_opt = magic_enum::enum_index(combatType); +size_t combatTypeToIndex(CombatType_t combatType, std::source_location location) { + const auto enum_index_opt = magic_enum::enum_index(combatType); if (enum_index_opt.has_value() && enum_index_opt.value() < COMBAT_COUNT) { return enum_index_opt.value(); } else { - g_logger().error("[{}] Combat type {} is out of range", __FUNCTION__, fmt::underlying(combatType)); + g_logger().error("[{}] Combat type {} is out of range, called line '{}:{}' in '{}'", __FUNCTION__, fmt::underlying(combatType), location.line(), location.column(), location.function_name()); // Uncomment for catch the function call with debug // throw std::out_of_range("Combat is out of range"); } @@ -1148,7 +1159,7 @@ size_t combatTypeToIndex(CombatType_t combatType) { } std::string combatTypeToName(CombatType_t combatType) { - std::string_view name = magic_enum::enum_name(combatType); + const std::string_view name = magic_enum::enum_name(combatType); if (!name.empty() && combatType < COMBAT_COUNT) { return formatEnumName(name); } else { @@ -1167,59 +1178,86 @@ CombatType_t indexToCombatType(size_t v) { ItemAttribute_t stringToItemAttribute(const std::string &str) { if (str == "store") { return ItemAttribute_t::STORE; - } else if (str == "aid") { + } + if (str == "aid") { return ItemAttribute_t::ACTIONID; - } else if (str == "uid") { + } + if (str == "uid") { return ItemAttribute_t::UNIQUEID; - } else if (str == "description") { + } + if (str == "description") { return ItemAttribute_t::DESCRIPTION; - } else if (str == "text") { + } + if (str == "text") { return ItemAttribute_t::TEXT; - } else if (str == "date") { + } + if (str == "date") { return ItemAttribute_t::DATE; - } else if (str == "writer") { + } + if (str == "writer") { return ItemAttribute_t::WRITER; - } else if (str == "name") { + } + if (str == "name") { return ItemAttribute_t::NAME; - } else if (str == "article") { + } + if (str == "article") { return ItemAttribute_t::ARTICLE; - } else if (str == "pluralname") { + } + if (str == "pluralname") { return ItemAttribute_t::PLURALNAME; - } else if (str == "weight") { + } + if (str == "weight") { return ItemAttribute_t::WEIGHT; - } else if (str == "attack") { + } + if (str == "attack") { return ItemAttribute_t::ATTACK; - } else if (str == "defense") { + } + if (str == "defense") { return ItemAttribute_t::DEFENSE; - } else if (str == "extradefense") { + } + if (str == "extradefense") { return ItemAttribute_t::EXTRADEFENSE; - } else if (str == "armor") { + } + if (str == "armor") { return ItemAttribute_t::ARMOR; - } else if (str == "hitchance") { + } + if (str == "hitchance") { return ItemAttribute_t::HITCHANCE; - } else if (str == "shootrange") { + } + if (str == "shootrange") { return ItemAttribute_t::SHOOTRANGE; - } else if (str == "owner") { + } + if (str == "owner") { return ItemAttribute_t::OWNER; - } else if (str == "duration") { + } + if (str == "duration") { return ItemAttribute_t::DURATION; - } else if (str == "decaystate") { + } + if (str == "decaystate") { return ItemAttribute_t::DECAYSTATE; - } else if (str == "corpseowner") { + } + if (str == "corpseowner") { return ItemAttribute_t::CORPSEOWNER; - } else if (str == "charges") { + } + if (str == "charges") { return ItemAttribute_t::CHARGES; - } else if (str == "fluidtype") { + } + if (str == "fluidtype") { return ItemAttribute_t::FLUIDTYPE; - } else if (str == "doorid") { + } + if (str == "doorid") { return ItemAttribute_t::DOORID; - } else if (str == "timestamp") { + } + if (str == "timestamp") { return ItemAttribute_t::DURATION_TIMESTAMP; - } else if (str == "amount") { + } + if (str == "amount") { return ItemAttribute_t::AMOUNT; - } else if (str == "tier") { + } + if (str == "tier") { return ItemAttribute_t::TIER; - } else if (str == "lootmessagesuffix") { + } + if (str == "lootmessagesuffix") { return ItemAttribute_t::LOOTMESSAGE_SUFFIX; } @@ -1523,22 +1561,34 @@ int64_t OTSYS_TIME(bool useTime) { } SpellGroup_t stringToSpellGroup(const std::string &value) { - std::string tmpStr = asLowerCaseString(value); + const std::string tmpStr = asLowerCaseString(value); if (tmpStr == "attack" || tmpStr == "1") { return SPELLGROUP_ATTACK; - } else if (tmpStr == "healing" || tmpStr == "2") { + } + if (tmpStr == "healing" || tmpStr == "2") { return SPELLGROUP_HEALING; - } else if (tmpStr == "support" || tmpStr == "3") { + } + if (tmpStr == "support" || tmpStr == "3") { return SPELLGROUP_SUPPORT; - } else if (tmpStr == "special" || tmpStr == "4") { + } + if (tmpStr == "special" || tmpStr == "4") { return SPELLGROUP_SPECIAL; - } else if (tmpStr == "crippling" || tmpStr == "6") { + } + if (tmpStr == "crippling" || tmpStr == "6") { return SPELLGROUP_CRIPPLING; - } else if (tmpStr == "focus" || tmpStr == "7") { + } + if (tmpStr == "focus" || tmpStr == "7") { return SPELLGROUP_FOCUS; - } else if (tmpStr == "ultimatestrikes" || tmpStr == "8") { + } + if (tmpStr == "ultimatestrikes" || tmpStr == "8") { return SPELLGROUP_ULTIMATESTRIKES; } + if (tmpStr == "burstsofnature" || tmpStr == "9") { + return SPELLGROUP_BURSTS_OF_NATURE; + } + if (tmpStr == "greatbeams" || tmpStr == "10") { + return SPELLGROUP_GREAT_BEAMS; + } return SPELLGROUP_NONE; } @@ -1551,20 +1601,20 @@ SpellGroup_t stringToSpellGroup(const std::string &value) { */ void capitalizeWords(std::string &source) { toLowerCaseString(source); - uint8_t size = (uint8_t)source.size(); + const auto size = static_cast<uint8_t>(source.size()); for (uint8_t i = 0; i < size; i++) { if (i == 0) { - source[i] = (char)toupper(source[i]); + source[i] = static_cast<char>(toupper(source[i])); } else if (source[i - 1] == ' ' || source[i - 1] == '\'') { source[i] = (char)toupper(source[i]); } } } -void capitalizeWordsIgnoringString(std::string &source, const std::string stringToIgnore) { +void capitalizeWordsIgnoringString(std::string &source, const std::string &stringToIgnore) { toLowerCaseString(source); - auto size = static_cast<uint8_t>(source.size()); - auto indexFound = source.find(stringToIgnore); + const auto size = static_cast<uint8_t>(source.size()); + const auto indexFound = source.find(stringToIgnore); for (uint8_t i = 0; i < size; i++) { if (indexFound != std::string::npos && indexFound > 0 && std::cmp_greater(i, static_cast<uint8_t>(indexFound - 1)) && i < (indexFound + stringToIgnore.size())) { @@ -1586,31 +1636,32 @@ void consoleHandlerExit() { if (isatty(STDIN_FILENO)) { getchar(); } - return; } NameEval_t validateName(const std::string &name) { StringVector prohibitedWords = { "owner", "gamemaster", "hoster", "admin", "staff", "tibia", "account", "god", "anal", "ass", "fuck", "sex", "hitler", "pussy", "dick", "rape", "cm", "gm", "tutor", "counsellor", "god" }; StringVector toks; - std::regex regexValidChars("^[a-zA-Z' ]+$"); + const std::regex regexValidChars("^[a-zA-Z' ]+$"); std::stringstream ss(name); - std::istream_iterator<std::string> begin(ss); - std::istream_iterator<std::string> end; + const std::istream_iterator<std::string> begin(ss); + const std::istream_iterator<std::string> end; std::copy(begin, end, std::back_inserter(toks)); if (name.length() < 3 || name.length() > 18) { return INVALID_LENGTH; } - if (!std::regex_match(name, regexValidChars)) { // invalid chars in name + if (!std::regex_match(name, regexValidChars)) { return INVALID_CHARACTER; } - for (std::string str : toks) { + for (const std::string &str : toks) { if (str.length() < 2) { return INVALID_TOKEN_LENGTH; - } else if (std::find(prohibitedWords.begin(), prohibitedWords.end(), str) != prohibitedWords.end()) { // searching for prohibited words + } + + if (std::ranges::find(prohibitedWords, str) != prohibitedWords.end()) { return INVALID_FORBIDDEN; } } @@ -1677,7 +1728,7 @@ std::string getObjectCategoryName(ObjectCategory_t category) { case OBJECTCATEGORY_DEFAULT: return "Unassigned Loot"; default: - return std::string(); + return {}; } } @@ -1720,31 +1771,31 @@ uint8_t forgeBonus(int32_t number) { return 0; } // Dust not consumed - else if (number >= 7400 && number < 9000) { + if (number >= 7400 && number < 9000) { return 1; } // Cores not consumed - else if (number >= 9000 && number < 9500) { + if (number >= 9000 && number < 9500) { return 2; } // Gold not consumed - else if (number >= 9500 && number < 9525) { + if (number >= 9500 && number < 9525) { return 3; } // Second item retained with decreased tier - else if (number >= 9525 && number < 9550) { + if (number >= 9525 && number < 9550) { return 4; } // Second item retained with unchanged tier - else if (number >= 9550 && number < 9950) { + if (number >= 9550 && number < 9950) { return 5; } // Second item retained with increased tier - else if (number >= 9950 && number < 9975) { + if (number >= 9950 && number < 9975) { return 6; } // Gain two tiers - else if (number >= 9975) { + if (number >= 9975) { return 7; } @@ -1752,9 +1803,9 @@ uint8_t forgeBonus(int32_t number) { } std::string formatPrice(std::string price, bool space /* = false*/) { - std::ranges::reverse(price.begin(), price.end()); + std::ranges::reverse(price); price = std::regex_replace(price, std::regex("000"), "k"); - std::ranges::reverse(price.begin(), price.end()); + std::ranges::reverse(price); if (space) { price = std::regex_replace(price, std::regex("k"), " k", std::regex_constants::format_first_only); } @@ -1875,9 +1926,9 @@ std::vector<std::string> split(const std::string &str, char delimiter /* = ','*/ } std::string getFormattedTimeRemaining(uint32_t time) { - time_t timeRemaining = time - getTimeNow(); + const time_t timeRemaining = time - getTimeNow(); - int days = static_cast<int>(std::floor(timeRemaining / 86400)); + const int days = static_cast<int>(std::floor(timeRemaining / 86400)); std::stringstream output; if (days > 1) { @@ -1885,9 +1936,9 @@ std::string getFormattedTimeRemaining(uint32_t time) { return output.str(); } - int hours = static_cast<int>(std::floor((timeRemaining % 86400) / 3600)); - int minutes = static_cast<int>(std::floor((timeRemaining % 3600) / 60)); - int seconds = static_cast<int>(timeRemaining % 60); + const auto hours = static_cast<int>(std::floor((timeRemaining % 86400) / 3600)); + const auto minutes = static_cast<int>(std::floor((timeRemaining % 3600) / 60)); + const auto seconds = static_cast<int>(timeRemaining % 60); if (hours == 0 && minutes == 0 && seconds > 0) { output << " less than 1 minute"; @@ -1967,8 +2018,10 @@ void sleep_for(uint64_t ms) { */ std::string toKey(const std::string &str) { std::string key = asLowerCaseString(str); - std::replace(key.begin(), key.end(), ' ', '-'); - key.erase(std::remove_if(key.begin(), key.end(), [](char c) { return std::isspace(c); }), key.end()); + std::ranges::replace(key, ' ', '-'); + std::erase_if(key, [](char c) { + return std::isspace(c); + }); return key; } @@ -2002,3 +2055,74 @@ bool caseInsensitiveCompare(std::string_view str1, std::string_view str2, size_t return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2)); }); } + +void printStackTrace() { + if (g_logger().getLevel() == "info") { + return; + } + + constexpr int kMaxFrames = 64; + std::array<void*, kMaxFrames> stack; + int numFrames = absl::GetStackTrace(stack.data(), kMaxFrames, 0); + absl::InitializeSymbolizer(""); + g_logger().info("Stack trace captured:"); + for (int i = 0; i < numFrames; ++i) { + char symbolBuffer[1024]; + if (absl::Symbolize(stack[i], symbolBuffer, sizeof(symbolBuffer))) { + g_logger().info("{}: {}", i, symbolBuffer); + } else { + g_logger().info("{}: [Unknown function]", i); + } + } +} + +const std::map<uint8_t, uint16_t> &getMaxValuePerSkill() { + static std::map<uint8_t, uint16_t> maxValuePerSkill = { + { SKILL_LIFE_LEECH_CHANCE, 100 }, + { SKILL_MANA_LEECH_CHANCE, 100 }, + { SKILL_CRITICAL_HIT_CHANCE, 100 * g_configManager().getNumber(CRITICALCHANCE) } + }; + + return maxValuePerSkill; +} + +float calculateEquipmentLoss(uint8_t blessingAmount, bool isContainer /* = false*/) { + float lossPercent = 0; + switch (blessingAmount) { + case 0: + lossPercent = 10; + break; + case 1: + lossPercent = 7; + break; + case 2: + lossPercent = 4.5; + break; + case 3: + lossPercent = 2.5; + break; + case 4: + lossPercent = 1; + break; + default: + // Blessing Amount >= 5 + lossPercent = 0; + break; + } + + return isContainer ? lossPercent * 10 : lossPercent; +} + +uint8_t calculateMaxPvpReduction(uint8_t blessCount, bool isPromoted /* = false*/) { + uint8_t result = 80 + (2 * blessCount) - (blessCount / 3); + + if (blessCount == 5) { + result -= 1; + } + + if (isPromoted) { + result += 6; + } + + return result; +} diff --git a/src/utils/tools.hpp b/src/utils/tools.hpp index e6acddd43f2..64fd2e8c1e6 100644 --- a/src/utils/tools.hpp +++ b/src/utils/tools.hpp @@ -10,7 +10,7 @@ #pragma once namespace pugi { - class xml_parse_result; + struct xml_parse_result; } struct Position; @@ -29,7 +29,7 @@ enum MoveEvent_t : uint8_t; enum NameEval_t : uint8_t; enum BedItemPart_t : uint8_t; enum ObjectCategory_t : uint8_t; -enum ItemAttribute_t : uint64_t; +enum class ItemAttribute_t : uint64_t; enum ReturnValue : uint16_t; enum SpellGroup_t : uint8_t; enum Cipbia_Elementals_t : uint8_t; @@ -77,7 +77,7 @@ int32_t uniform_random(int32_t minNumber, int32_t maxNumber); int32_t normal_random(int32_t minNumber, int32_t maxNumber); bool boolean_random(double probability = 0.5); -BedItemPart_t getBedPart(const std::string_view string); +BedItemPart_t getBedPart(std::string_view string); Direction getDirection(const std::string &string); Position getNextPosition(Direction direction, Position pos); @@ -137,7 +137,7 @@ CombatType_t getCombatTypeByName(const std::string &combatname); * @return The corresponding index of the CombatType_t enumeration. * If the CombatType_t is out of range, this function will log an error and return an empty size_t. */ -size_t combatTypeToIndex(CombatType_t combatType); +size_t combatTypeToIndex(CombatType_t combatType, std::source_location location = std::source_location::current()); /** * @brief Convert the CombatType_t enumeration to its corresponding string representation. @@ -155,7 +155,7 @@ const char* getReturnMessage(ReturnValue value); void sleep_for(uint64_t ms); void capitalizeWords(std::string &source); -void capitalizeWordsIgnoringString(std::string &source, const std::string stringToIgnore); +void capitalizeWordsIgnoringString(std::string &source, const std::string &stringToIgnore); void consoleHandlerExit(); NameEval_t validateName(const std::string &name); @@ -208,3 +208,10 @@ EnumType enumFromValue(UnderlyingType value) { } bool caseInsensitiveCompare(std::string_view str1, std::string_view str2, size_t length = std::string_view::npos); + +void printStackTrace(); + +const std::map<uint8_t, uint16_t> &getMaxValuePerSkill(); + +float calculateEquipmentLoss(uint8_t blessingAmount, bool isContainer = false); +uint8_t calculateMaxPvpReduction(uint8_t blessCount, bool isPromoted = false); diff --git a/src/utils/vectorsort.hpp b/src/utils/vectorsort.hpp index 0a3618b963f..c9dc35e0d4a 100644 --- a/src/utils/vectorsort.hpp +++ b/src/utils/vectorsort.hpp @@ -27,7 +27,7 @@ namespace stdext { bool erase(const T &v) { update(); - const auto &it = std::ranges::lower_bound(container, v); + auto it = std::ranges::lower_bound(container, v); if (it == container.end()) { return false; } diff --git a/src/utils/wildcardtree.cpp b/src/utils/wildcardtree.cpp index a8ddf98e442..37f29caa2c5 100644 --- a/src/utils/wildcardtree.cpp +++ b/src/utils/wildcardtree.cpp @@ -10,7 +10,7 @@ #include "utils/wildcardtree.hpp" std::shared_ptr<WildcardTreeNode> WildcardTreeNode::getChild(char ch) { - auto it = children.find(ch); + const auto it = children.find(ch); if (it == children.end()) { return nullptr; } @@ -18,7 +18,7 @@ std::shared_ptr<WildcardTreeNode> WildcardTreeNode::getChild(char ch) { } std::shared_ptr<WildcardTreeNode> WildcardTreeNode::getChild(char ch) const { - auto it = children.find(ch); + const auto it = children.find(ch); if (it == children.end()) { return nullptr; } @@ -26,22 +26,22 @@ std::shared_ptr<WildcardTreeNode> WildcardTreeNode::getChild(char ch) const { } std::shared_ptr<WildcardTreeNode> WildcardTreeNode::addChild(char ch, bool breakp) { - std::shared_ptr<WildcardTreeNode> child = getChild(ch); + auto child = getChild(ch); if (child) { if (breakp && !child->breakpoint) { child->breakpoint = true; } } else { - auto pair = children.emplace(std::piecewise_construct, std::forward_as_tuple(ch), std::forward_as_tuple(std::make_shared<WildcardTreeNode>(breakp))); - child = pair.first->second; + const auto [fst, snd] = children.emplace(std::piecewise_construct, std::forward_as_tuple(ch), std::forward_as_tuple(std::make_shared<WildcardTreeNode>(breakp))); + child = fst->second; } return child; } void WildcardTreeNode::insert(const std::string &str) { - std::shared_ptr<WildcardTreeNode> cur = static_self_cast<WildcardTreeNode>(); + auto cur = static_self_cast<WildcardTreeNode>(); - size_t length = str.length() - 1; + const size_t length = str.length() - 1; for (size_t pos = 0; pos < length; ++pos) { cur = cur->addChild(str[pos], false); } @@ -50,7 +50,7 @@ void WildcardTreeNode::insert(const std::string &str) { } void WildcardTreeNode::remove(const std::string &str) { - std::shared_ptr<WildcardTreeNode> cur = static_self_cast<WildcardTreeNode>(); + auto cur = static_self_cast<WildcardTreeNode>(); std::stack<std::shared_ptr<WildcardTreeNode>> path; path.push(cur); @@ -84,7 +84,7 @@ void WildcardTreeNode::remove(const std::string &str) { ReturnValue WildcardTreeNode::findOne(const std::string &query, std::string &result) const { auto cur = static_self_cast<const WildcardTreeNode>(); - for (char pos : query) { + for (const char &pos : query) { cur = cur->getChild(pos); if (!cur) { return RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE; @@ -94,14 +94,14 @@ ReturnValue WildcardTreeNode::findOne(const std::string &query, std::string &res result = query; do { - size_t size = cur->children.size(); + const size_t size = cur->children.size(); if (size == 0) { return RETURNVALUE_NOERROR; } else if (size > 1 || cur->breakpoint) { return RETURNVALUE_NAMEISTOOAMBIGUOUS; } - auto it = cur->children.begin(); + const auto it = cur->children.begin(); result += it->first; cur = it->second; } while (true); diff --git a/src/utils/wildcardtree.hpp b/src/utils/wildcardtree.hpp index 9f3d2cf8ece..ccbad316ebd 100644 --- a/src/utils/wildcardtree.hpp +++ b/src/utils/wildcardtree.hpp @@ -11,7 +11,7 @@ #include "declarations.hpp" -class WildcardTreeNode : public SharedObject { +class WildcardTreeNode final : public SharedObject { public: explicit WildcardTreeNode(bool initBreakpoint) : breakpoint(initBreakpoint) { } diff --git a/tests/fixture/account/in_memory_account_repository.hpp b/tests/fixture/account/in_memory_account_repository.hpp index 8a294992274..d86d6a483be 100644 --- a/tests/fixture/account/in_memory_account_repository.hpp +++ b/tests/fixture/account/in_memory_account_repository.hpp @@ -33,10 +33,10 @@ namespace tests { accounts[descriptor] = acc; } - bool loadByID(const uint32_t &id, AccountInfo &acc) final { + bool loadByID(const uint32_t &id, std::unique_ptr<AccountInfo> &acc) final { for (const auto &account : accounts) { if (account.second.id == id) { - acc = account.second; + acc = std::make_unique<AccountInfo>(account.second); return true; } } @@ -44,29 +44,29 @@ namespace tests { return false; } - bool loadByEmailOrName(bool oldProtocol, const std::string &email, AccountInfo &acc) final { + bool loadByEmailOrName(bool oldProtocol, const std::string &email, std::unique_ptr<AccountInfo> &acc) final { auto account = accounts.find(email); if (account == accounts.end()) { return false; } - acc = account->second; + acc = std::make_unique<AccountInfo>(account->second); return true; } - bool loadBySession(const std::string &sessionKey, AccountInfo &acc) final { + bool loadBySession(const std::string &sessionKey, std::unique_ptr<AccountInfo> &acc) final { auto account = accounts.find(sessionKey); if (account == accounts.end()) { return false; } - acc = account->second; + acc = std::make_unique<AccountInfo>(account->second); return true; } - bool save(const AccountInfo &accInfo) final { + bool save(const std::unique_ptr<AccountInfo> &accInfo) final { return !failSave; } @@ -75,7 +75,7 @@ namespace tests { return !failGetPassword; } - bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) final { + bool getCoins(const uint32_t &id, CoinType type, uint32_t &coins) final { auto accountCoins = coins_.find(id); if (accountCoins == coins_.end()) { @@ -92,11 +92,11 @@ namespace tests { return true; } - bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) final { + bool setCoins(const uint32_t &id, CoinType type, const uint32_t &amount) final { auto accountCoins = coins_.find(id); if (accountCoins == coins_.end()) { - coins_[id] = phmap::flat_hash_map<uint8_t, uint32_t>(); + coins_[id] = phmap::flat_hash_map<CoinType, uint32_t>(); } coins_[id][type] = amount; @@ -105,15 +105,15 @@ namespace tests { bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) final { auto accountCoins = coinsTransactions_.find(id); if (accountCoins == coinsTransactions_.end()) { - coinsTransactions_[id] = std::vector<std::tuple<uint8_t, uint32_t, uint8_t, std::string>>(); + coinsTransactions_[id] = std::vector<std::tuple<CoinTransactionType, uint32_t, CoinType, std::string>>(); } coinsTransactions_[id].emplace_back(type, coins, coinType, description); @@ -150,8 +150,8 @@ namespace tests { bool failAuthenticateFromSession = false; std::string password_ = "123456"; phmap::flat_hash_map<std::string, AccountInfo> accounts; - phmap::flat_hash_map<uint32_t, phmap::flat_hash_map<uint8_t, uint32_t>> coins_; - phmap::flat_hash_map<uint32_t, std::vector<std::tuple<uint8_t, uint32_t, uint8_t, std::string>>> coinsTransactions_; + phmap::flat_hash_map<uint32_t, phmap::flat_hash_map<CoinType, uint32_t>> coins_; + phmap::flat_hash_map<uint32_t, std::vector<std::tuple<CoinTransactionType, uint32_t, CoinType, std::string>>> coinsTransactions_; }; } diff --git a/tests/integration/main.cpp b/tests/integration/main.cpp index 6fb0c291e49..019c385243d 100644 --- a/tests/integration/main.cpp +++ b/tests/integration/main.cpp @@ -36,15 +36,15 @@ void createAccount(Database &db) { )); } -void assertAccountLoad(AccountInfo acc) { - expect(eq(acc.id, 111)); - expect(eq(acc.accountType, AccountType::ACCOUNT_TYPE_SENIORTUTOR)); - expect(eq(acc.premiumRemainingDays, 11)); - expect(eq(acc.premiumLastDay, 1293912)); - expect(eq(acc.players.size(), 0)); - expect(eq(acc.oldProtocol, false)); - expect(eq(acc.premiumDaysPurchased, 11)); - expect(approx(acc.creationTime, 42183281, 60 * 60 * 1000)); +void assertAccountLoad(const std::unique_ptr<AccountInfo> &acc) { + expect(eq(acc->id, 111)); + expect(eq(acc->accountType, AccountType::ACCOUNT_TYPE_SENIORTUTOR)); + expect(eq(acc->premiumRemainingDays, 11)); + expect(eq(acc->premiumLastDay, 1293912)); + expect(eq(acc->players.size(), 0)); + expect(eq(acc->oldProtocol, false)); + expect(eq(acc->premiumDaysPurchased, 11)); + expect(approx(acc->creationTime, 42183281, 60 * 60 * 1000)); } int main() { @@ -74,10 +74,10 @@ int main() { AccountRepositoryDB accRepo{}; createAccount(db); - AccountInfo acc{}; + auto acc = std::make_unique<AccountInfo>(); accRepo.loadByID(111, acc); assertAccountLoad(acc); - expect(eq(acc.sessionExpires, 0)); + expect(eq(acc->sessionExpires, 0)); }); test("AccountRepositoryDB::loadByEmailOrName") = databaseTest(db, [&db] { @@ -85,10 +85,10 @@ int main() { AccountRepositoryDB accRepo {}; createAccount(db); - AccountInfo acc {}; + auto acc = std::make_unique<AccountInfo>(); accRepo.loadByEmailOrName(false, "@test", acc); assertAccountLoad(acc); - expect(eq(acc.sessionExpires, 0)); + expect(eq(acc->sessionExpires, 0)); }); test("AccountRepositoryDB::loadBySession") = databaseTest(db, [&db] { @@ -96,25 +96,25 @@ int main() { AccountRepositoryDB accRepo {}; createAccount(db); - AccountInfo acc {}; + auto acc = std::make_unique<AccountInfo>(); accRepo.loadBySession("test", acc); assertAccountLoad(acc); - expect(eq(acc.sessionExpires, 1337)); + expect(eq(acc->sessionExpires, 1337)); }); test("AccountRepositoryDB load sets premium day purchased = remaining days, if needed") = databaseTest(db, [&db] { InMemoryLogger logger{}; AccountRepositoryDB accRepo{}; - AccountInfo acc{}; + auto acc = std::make_unique<AccountInfo>(); accRepo.loadByID(1, acc); - acc.premiumRemainingDays = 10; + acc->premiumRemainingDays = 10; accRepo.save(acc); accRepo.loadByID(1, acc); - expect(eq(acc.premiumDaysPurchased, 10)); + expect(eq(acc->premiumDaysPurchased, 10)); }); test("AccountRepositoryDB::getPassword") = databaseTest(db, [&db] { @@ -143,21 +143,21 @@ int main() { InMemoryLogger logger {}; AccountRepositoryDB accRepo {}; - AccountInfo acc {}; - acc.id = 1; - acc.accountType = AccountType::ACCOUNT_TYPE_SENIORTUTOR; - acc.premiumRemainingDays = 10; - acc.premiumLastDay = 10; - acc.sessionExpires = 99999999; + auto acc = std::make_unique<AccountInfo>(); + acc->id = 1; + acc->accountType = AccountType::ACCOUNT_TYPE_SENIORTUTOR; + acc->premiumRemainingDays = 10; + acc->premiumLastDay = 10; + acc->sessionExpires = 99999999; expect(accRepo.save(acc)); - AccountInfo acc2 {}; + auto acc2 = std::make_unique<AccountInfo>(); accRepo.loadByID(1, acc2); - expect(eq(acc2.id, 1)); - expect(eq(acc2.accountType, AccountType::ACCOUNT_TYPE_SENIORTUTOR)); - expect(eq(acc2.premiumRemainingDays, 10)); - expect(eq(acc2.premiumLastDay, 10)); + expect(eq(acc2->id, 1)); + expect(eq(acc2->accountType, AccountType::ACCOUNT_TYPE_SENIORTUTOR)); + expect(eq(acc2->premiumRemainingDays, 10)); + expect(eq(acc2->premiumLastDay, 10)); // sessionExpires is not saved - expect(eq(acc2.sessionExpires, 0)); + expect(eq(acc2->sessionExpires, 0)); }); } diff --git a/tests/unit/account/account_test.cpp b/tests/unit/account/account_test.cpp index c0c3ebbb832..5ff6322769d 100644 --- a/tests/unit/account/account_test.cpp +++ b/tests/unit/account/account_test.cpp @@ -19,49 +19,65 @@ #include "enums/account_group_type.hpp" #include "utils/tools.hpp" +using namespace boost::ut; +using namespace std; + +template <typename T, typename U> +bool eqEnum(const T& lhs, const U& rhs) { + if constexpr (std::is_enum_v<T> && std::is_enum_v<U>) { + return enumToValue(lhs) == enumToValue(rhs); + } else if constexpr (std::is_enum_v<T>) { + return enumToValue(lhs) == rhs; + } else if constexpr (std::is_enum_v<U>) { + return lhs == enumToValue(rhs); + } else { + return lhs == rhs; + } +} + suite<"account"> accountTest = [] { - InjectionFixture injectionFixture {}; + InjectionFixture injectionFixture{}; + test("Account::Account default constructors") = [] { - Account byId { 1 }, byDescriptor { "canary@test.com" }; + shared_ptr<Account> byId = make_shared<Account>(1); + shared_ptr<Account> byDescriptor = make_shared<Account>("canary@test.com"); - expect(eq(byId.getID(), 1)); - expect(eq(byDescriptor.getID(), 0)); + expect(eq(byId->getID(), 1)); + expect(eq(byDescriptor->getID(), 0)); - expect(byId.getDescriptor().empty()); - expect(eq(byDescriptor.getDescriptor(), std::string { "canary@test.com" })); + expect(byId->getDescriptor().empty()); + expect(eq(byDescriptor->getDescriptor(), string{"canary@test.com"})); - for (auto &account : { byId, byDescriptor }) { - expect( - eq(account.getPremiumRemainingDays(), 0) and - eq(account.getPremiumLastDay(), 0) and - eq(account.getAccountType(), AccountType::ACCOUNT_TYPE_NORMAL) - ); + for (auto& account : { byId, byDescriptor }) { + expect(eq(account->getPremiumRemainingDays(), 0)); + expect(eq(account->getPremiumLastDay(), 0)); + expect(eqEnum(account->getAccountType(), AccountType::ACCOUNT_TYPE_NORMAL)); } }; struct AccountLoadTestCase { - std::string description; - Account account; + string description; + shared_ptr<Account> account; AccountErrors_t expectedError; }; - std::vector<AccountLoadTestCase> accountLoadTestCases { - { "returns by id if exists", Account { 1 }, AccountErrors_t::Ok }, - { "returns by descriptor if exists", Account { "canary@test.com" }, AccountErrors_t::Ok }, - { "returns error if id is not valid", Account { 2 }, AccountErrors_t::LoadingAccount }, - { "returns error if descriptor is not valid", Account { "not@valid.com" }, AccountErrors_t::LoadingAccount } + vector<AccountLoadTestCase> accountLoadTestCases{ + {"returns by id if exists", make_shared<Account>(1), AccountErrors_t::Ok}, + {"returns by descriptor if exists", make_shared<Account>("canary@test.com"), AccountErrors_t::Ok}, + {"returns error if id is not valid", make_shared<Account>(2), AccountErrors_t::LoadingAccount}, + {"returns error if descriptor is not valid", make_shared<Account>("not@valid.com"), AccountErrors_t::LoadingAccount} }; - for (auto accountLoadTestCase : accountLoadTestCases) { - test(accountLoadTestCase.description) = [&injectionFixture, &accountLoadTestCase] { + for (auto& testCase : accountLoadTestCases) { + test(testCase.description) = [&injectionFixture, &testCase] { auto [accountRepository] = injectionFixture.get<AccountRepository>(); - accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(accountLoadTestCase.account.load(), enumToValue(accountLoadTestCase.expectedError))) << accountLoadTestCase.description; + accountRepository.addAccount("canary@test.com", AccountInfo{1, 1, 1, AccountType::ACCOUNT_TYPE_GOD}); + expect(eqEnum(testCase.account->load(), testCase.expectedError)) << testCase.description; }; } test("Account::reload returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.reload(), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.reload(), AccountErrors_t::NotInitialized)); }; test("Account::reload reloads account info") = [&injectionFixture] { @@ -70,21 +86,17 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GOD) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GOD)); accountRepository.addAccount("canary2@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GAMEMASTER }); - expect( - eq(acc.reload(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER) - ); + expect(eqEnum(acc.reload(), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER)); }; test("Account::save returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.save(), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.save(), AccountErrors_t::NotInitialized)); }; test("Account::save returns error if it fails") = [&injectionFixture] { @@ -94,7 +106,8 @@ suite<"account"> accountTest = [] { accountRepository.failSave = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok) and eq(acc.save(), enumToValue(AccountErrors_t::Storage)))); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.save(), AccountErrors_t::Storage)); }; test("Account::save saves account info") = [&injectionFixture] { @@ -104,11 +117,12 @@ suite<"account"> accountTest = [] { accountRepository.failSave = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok) and eq(acc.save(), enumToValue(AccountErrors_t::Ok)))); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.save(), AccountErrors_t::Ok)); }; test("Account::getCoins returns error if not yet loaded") = [&injectionFixture] { - expect(eq(std::get<1>(Account { 1 }.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(std::get<1>(Account { 1 }.getCoins(CoinType::Normal)), AccountErrors_t::NotInitialized)); }; test("Account::getCoins returns error if it fails") = [&injectionFixture] { @@ -117,10 +131,8 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Storage)); }; test("Account::getCoins returns coins") = [&injectionFixture] { @@ -128,13 +140,11 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::getCoins returns coins for specified account only") = [&injectionFixture] { @@ -142,16 +152,14 @@ suite<"account"> accountTest = [] { Account acc { 2 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 33) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 33)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::getCoins returns coins for specified coin type only") = [&injectionFixture] { @@ -159,20 +167,18 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 100); - - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 100); + + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); }; test("Account::addCoins returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.addCoins(CoinType::Normal, 100), AccountErrors_t::NotInitialized)); }; test("Account::addCoins returns error if it fails") = [&injectionFixture] { @@ -181,12 +187,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Storage)); }; test("Account::addCoins returns error if get coins fail") = [&injectionFixture] { @@ -194,12 +198,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Tournament), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Tournament, 100), AccountErrors_t::Storage)); }; test("Account::addCoins adds coins") = [&injectionFixture] { @@ -208,14 +210,12 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) - and eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 200) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 200)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::addCoins adds coins for specified account only") = [&injectionFixture] { @@ -224,17 +224,15 @@ suite<"account"> accountTest = [] { Account acc { 2 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 133) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 133)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::addCoins adds coins for specified coin type only") = [&injectionFixture] { @@ -242,33 +240,29 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 57); - accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 200) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 57) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 57); + accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); + + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 200)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 57)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType, enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Add)) and - eq(description, std::string { "ADD Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType, CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Add)); + expect(eq(description, std::string { "ADD Coins" })); }; test("Account::removeCoins returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.removeCoins(CoinType::Normal, 100), AccountErrors_t::NotInitialized)); }; test("Account::removeCoins returns error if it fails") = [&injectionFixture] { @@ -277,12 +271,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Storage)); }; test("Account::removeCoins returns error if get coins fail") = [&injectionFixture] { @@ -290,12 +282,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Tournament), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Tournament, 100), AccountErrors_t::Storage)); }; test("Account::removeCoins removes coins") = [&injectionFixture] { @@ -304,14 +294,12 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::removeCoins removes coins for specified account only") = [&injectionFixture] { @@ -320,17 +308,15 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::removeCoins removes coins for specified coin type only") = [&injectionFixture] { @@ -339,28 +325,24 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 57); - - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 57) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 57); + + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 57)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType, enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Remove)) and - eq(description, std::string { "REMOVE Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType, CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Remove)); + expect(eq(description, std::string { "REMOVE Coins" })); }; test("Account::removeCoins returns error if account doesn't have enough coins") = [&injectionFixture] { @@ -368,38 +350,30 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 1); + accountRepository.setCoins(1, CoinType::Normal, 1); accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 50); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + accountRepository.setCoins(1, CoinType::Normal, 50); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType,enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Remove)) and - eq(description, std::string { "REMOVE Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType,CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Remove)); + expect(eq(description, std::string { "REMOVE Coins" })); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); @@ -410,23 +384,23 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok))); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 1); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + accountRepository.setCoins(1, CoinType::Normal, 1); - expect(eq(acc.addCoins(enumToValue(CoinType::Normal), 100, ""), enumToValue(AccountErrors_t::Ok))); - expect(eq(acc.removeCoins(enumToValue(CoinType::Normal), 80, ""), enumToValue(AccountErrors_t::Ok))); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100, ""), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 80, ""), AccountErrors_t::Ok)); - expect(eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 21)); - expect(eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok))); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 21)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); - acc.registerCoinTransaction(enumToValue(CoinTransactionType::Add), enumToValue(CoinType::Normal), 100, ""); - acc.registerCoinTransaction(enumToValue(CoinTransactionType::Remove), enumToValue(CoinType::Normal), 100, ""); + acc.registerCoinTransaction(CoinTransactionType::Add, CoinType::Normal, 100, ""); + acc.registerCoinTransaction(CoinTransactionType::Remove, CoinType::Normal, 100, ""); expect(eq(accountRepository.coinsTransactions_.size(), 0)); }; test("Account::getPassword returns empty string if not yet loaded") = [] { - expect(eq(Account { 1 }.getPassword(), std::string { "" })); + expect(eqEnum(Account { 1 }.getPassword(), std::string { "" })); }; test("Account::getPassword returns password") = [&injectionFixture] { @@ -435,10 +409,8 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getPassword(), std::string { "123456" }) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eq(acc.getPassword(), std::string { "123456" })); }; test("Account::getPassword returns logs error if it fails") = [&injectionFixture] { @@ -448,12 +420,10 @@ suite<"account"> accountTest = [] { accountRepository.failGetPassword = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::string{}, acc.getPassword()) and - eq(std::string{"error"}, logger.logs[0].level) and - eq(std::string{"Failed to get password for account[1]!"}, logger.logs[0].message) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eq(std::string{}, acc.getPassword())); + expect(eq(std::string{"error"}, logger.logs[0].level)); + expect(eq(std::string{"Failed to get password for account[1]!"}, logger.logs[0].message)); }; test("Account::addPremiumDays sets premium remaining days") = [] { @@ -469,10 +439,8 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(50); acc.addPremiumDays(50); - expect( - approx(acc.getPremiumLastDay(), getTimeNow() + (100 * 86400), 60 * 60 * 1000) and - eq(acc.getPremiumRemainingDays(), 100) - ); + expect(approx(acc.getPremiumLastDay(), getTimeNow() + (100 * 86400), 60 * 60 * 1000)); + expect(eq(acc.getPremiumRemainingDays(), 100)); }; test("Account::addPremiumDays can reduce premium") = [] { @@ -481,10 +449,8 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(50); acc.addPremiumDays(-30); - expect( - approx(acc.getPremiumLastDay(), getTimeNow() - (20 * 86400), 60 * 60 * 1000) and - eq(acc.getPremiumRemainingDays(), 20) - ); + expect(approx(acc.getPremiumLastDay(), getTimeNow() - (20 * 86400), 60 * 60 * 1000)); + expect(eq(acc.getPremiumRemainingDays(), 20)); }; test("Account::setPremiumDays sets to 0 if day is negative") = [] { @@ -492,18 +458,14 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(10); acc.setPremiumDays(-20); - expect( - eq(acc.getPremiumLastDay(), 0) and - eq(acc.getPremiumLastDay(), 0) - ); + expect(eq(acc.getPremiumLastDay(), 0)); + expect(eq(acc.getPremiumLastDay(), 0)); }; test("Account::setAccountType sets account type") = [] { Account acc { 1 }; - expect( - eq(acc.setAccountType(AccountType::ACCOUNT_TYPE_GAMEMASTER), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER) - ); + expect(eqEnum(acc.setAccountType(AccountType::ACCOUNT_TYPE_GAMEMASTER), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER)); }; test("Account::updatePremiumTime sets premium remaining days to 0 if last day is in the past") = [] { @@ -543,7 +505,7 @@ suite<"account"> accountTest = [] { }; test("Account::getAccountPlayer returns error if not yet loaded") = [] { - expect(eq(std::get<1>(Account { 1 }.getAccountPlayers()), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(std::get<1>(Account { 1 }.getAccountPlayers()), AccountErrors_t::NotInitialized)); }; test("Account::getAccountPlayer returns players") = [&injectionFixture] { @@ -555,15 +517,13 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, {{ "Canary", 1 }, { "Canary2", 2 }} } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); auto [players, error] = acc.getAccountPlayers(); - expect( - eq(error, enumToValue(AccountErrors_t::Ok)) and - eq(players.size(), 2) and - eq(players["Canary"], 1) and - eq(players["Canary2"], 2) - ); + expect(eqEnum(error, AccountErrors_t::Ok)); + expect(eq(players.size(), 2)); + expect(eq(players["Canary"], 1)); + expect(eq(players["Canary2"], 2)); }; test("Account::authenticate password using sha1") = [&injectionFixture] { @@ -575,7 +535,7 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, { { "Canary", 1 }, { "Canary2", 2 } } } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); accountRepository.password_ = "7c4a8d09ca3762af61e59520943dc26494f8941b"; expect(acc.authenticate("123456")); }; @@ -589,7 +549,7 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, { { "Canary", 1 }, { "Canary2", 2 } }, false, getTimeNow() + 24 * 60 * 60 * 1000 } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); expect(acc.authenticate()); }; diff --git a/vcpkg.json b/vcpkg.json index 94dd5d16599..34bfee7a84b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -20,6 +20,7 @@ "spdlog", "zlib", "bshoshany-thread-pool", + "atomic-queue", { "name": "opentelemetry-cpp", "default-features": true, diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index 7cbdd118ccc..6436dd704a9 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -137,7 +137,6 @@ <ClInclude Include="..\src\lua\functions\core\game\zone_functions.hpp" /> <ClInclude Include="..\src\lua\functions\core\game\lua_enums.hpp" /> <ClInclude Include="..\src\lua\functions\core\game\modal_window_functions.hpp" /> - <ClInclude Include="..\src\lua\functions\core\libs\bit_functions.hpp" /> <ClInclude Include="..\src\lua\functions\core\libs\core_libs_functions.hpp" /> <ClInclude Include="..\src\lua\functions\core\libs\kv_functions.hpp" /> <ClInclude Include="..\src\lua\functions\core\libs\db_functions.hpp" /> @@ -336,7 +335,6 @@ <ClCompile Include="..\src\lua\functions\core\game\zone_functions.cpp" /> <ClCompile Include="..\src\lua\functions\core\game\lua_enums.cpp" /> <ClCompile Include="..\src\lua\functions\core\game\modal_window_functions.cpp" /> - <ClCompile Include="..\src\lua\functions\core\libs\bit_functions.cpp" /> <ClCompile Include="..\src\lua\functions\core\libs\kv_functions.cpp" /> <ClCompile Include="..\src\lua\functions\core\libs\db_functions.cpp" /> <ClCompile Include="..\src\lua\functions\core\libs\result_functions.cpp" />