From dabbeada591b89445c73d4e8a524fff640f8a7c9 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Fri, 24 May 2024 22:14:53 -0300 Subject: [PATCH 01/17] fix: vip groups schema (#2651) Fixes the schema of vip groups. --- schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema.sql b/schema.sql index 7bbf6c86ac5..bf37d1c2f37 100644 --- a/schema.sql +++ b/schema.sql @@ -854,7 +854,7 @@ INSERT INTO `players` (6, 'GOD', 6, 1, 2, 0, 155, 155, 100, 113, 115, 95, 39, 75, 0, 60, 60, 0, 8, '', 410, 1, 10, 0, 10, 0, 10, 0, 10, 0); -- Create vip groups for GOD account -INSERT INTO `account_vipgroups` (`id`, `name`, `account_id`. `customizable`) VALUES +INSERT INTO `account_vipgroups` (`id`, `name`, `account_id`, `customizable`) VALUES (1, 'Friends', 1, 0), (2, 'Enemies', 1, 0), (3, 'Trading Partners', 1, 0); From b9a2336247cc246ef3ddc8baea719e108041ad83 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 28 May 2024 20:27:19 -0300 Subject: [PATCH 02/17] perf: change ThreadPool by ASIO to barak shoshany (#2660) Replaces the existing ThreadPool with ASIO to enhance server performance, implementing a strategy inspired by Barak Shoshany's methodology. The goal is to optimize asynchronous task execution and thread management for improved scalability and efficiency https://github.com/bshoshany/thread-pool --------- Co-authored-by: GitHub Actions Co-authored-by: Eduardo Dantas --- CMakeLists.txt | 4 +- src/database/databasetasks.cpp | 4 +- src/game/scheduling/dispatcher.cpp | 6 +- src/game/scheduling/dispatcher.hpp | 2 +- src/game/scheduling/save_manager.cpp | 4 +- src/lib/thread/README.md | 2 +- src/lib/thread/thread_pool.cpp | 77 ++++---------------------- src/lib/thread/thread_pool.hpp | 19 +++---- src/server/network/webhook/webhook.cpp | 2 +- vcpkg.json | 1 + 10 files changed, 30 insertions(+), 91 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52c35a471f7..07701451aad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.22 FATAL_ERROR) # VCPKG # cmake -DCMAKE_TOOLCHAIN_FILE=/opt/workspace/vcpkg/scripts/buildsystems/vcpkg.cmake .. # Needed libs is in file vcpkg.json -# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil +# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil bshoshany-thread-pool if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") @@ -124,4 +124,4 @@ add_subdirectory(src) if(BUILD_TESTS) add_subdirectory(tests) -endif() \ No newline at end of file +endif() diff --git a/src/database/databasetasks.cpp b/src/database/databasetasks.cpp index 6d43992ac81..06cfda93fc0 100644 --- a/src/database/databasetasks.cpp +++ b/src/database/databasetasks.cpp @@ -23,7 +23,7 @@ DatabaseTasks &DatabaseTasks::getInstance() { } void DatabaseTasks::execute(const std::string &query, std::function callback /* nullptr */) { - threadPool.addLoad([this, query, callback]() { + threadPool.detach_task([this, query, callback]() { bool success = db.executeQuery(query); if (callback != nullptr) { g_dispatcher().addEvent([callback, success]() { callback(nullptr, success); }, "DatabaseTasks::execute"); @@ -32,7 +32,7 @@ void DatabaseTasks::execute(const std::string &query, std::function callback /* nullptr */) { - threadPool.addLoad([this, query, callback]() { + threadPool.detach_task([this, query, callback]() { DBResult_ptr result = db.storeQuery(query); if (callback != nullptr) { g_dispatcher().addEvent([callback, result]() { callback(result, true); }, "DatabaseTasks::store"); diff --git a/src/game/scheduling/dispatcher.cpp b/src/game/scheduling/dispatcher.cpp index ec999848a92..7cff69d66bf 100644 --- a/src/game/scheduling/dispatcher.cpp +++ b/src/game/scheduling/dispatcher.cpp @@ -23,10 +23,10 @@ Dispatcher &Dispatcher::getInstance() { void Dispatcher::init() { UPDATE_OTSYS_TIME(); - threadPool.addLoad([this] { + threadPool.detach_task([this] { std::unique_lock asyncLock(dummyMutex); - while (!threadPool.getIoContext().stopped()) { + while (!threadPool.isStopped()) { UPDATE_OTSYS_TIME(); executeEvents(); @@ -60,7 +60,7 @@ void Dispatcher::executeParallelEvents(std::vector &tasks, const uint8_t g std::atomic_bool isTasksCompleted = false; for (const auto &task : tasks) { - threadPool.addLoad([groupId, &task, &isTasksCompleted, &totalTaskSize] { + threadPool.detach_task([groupId, &task, &isTasksCompleted, &totalTaskSize] { dispacherContext.type = DispatcherType::AsyncEvent; dispacherContext.group = static_cast(groupId); dispacherContext.taskName = task.getContext(); diff --git a/src/game/scheduling/dispatcher.hpp b/src/game/scheduling/dispatcher.hpp index d9e26a0b5d5..a6cbc8dd6dd 100644 --- a/src/game/scheduling/dispatcher.hpp +++ b/src/game/scheduling/dispatcher.hpp @@ -84,7 +84,7 @@ class Dispatcher { public: explicit Dispatcher(ThreadPool &threadPool) : threadPool(threadPool) { - threads.reserve(threadPool.getNumberOfThreads() + 1); + threads.reserve(threadPool.get_thread_count() + 1); for (uint_fast16_t i = 0; i < threads.capacity(); ++i) { threads.emplace_back(std::make_unique()); } diff --git a/src/game/scheduling/save_manager.cpp b/src/game/scheduling/save_manager.cpp index 2c1eff6657c..fbad528598b 100644 --- a/src/game/scheduling/save_manager.cpp +++ b/src/game/scheduling/save_manager.cpp @@ -41,7 +41,7 @@ void SaveManager::scheduleAll() { return; } - threadPool.addLoad([this, scheduledAt]() { + threadPool.detach_task([this, scheduledAt]() { if (m_scheduledAt.load() != scheduledAt) { logger.warn("Skipping save for server because another save has been scheduled."); return; @@ -69,7 +69,7 @@ void SaveManager::schedulePlayer(std::weak_ptr playerPtr) { logger.debug("Scheduling player {} for saving.", playerToSave->getName()); auto scheduledAt = std::chrono::steady_clock::now(); m_playerMap[playerToSave->getGUID()] = scheduledAt; - threadPool.addLoad([this, playerPtr, scheduledAt]() { + threadPool.detach_task([this, playerPtr, scheduledAt]() { auto player = playerPtr.lock(); if (!player) { logger.debug("Skipping save for player because player is no longer online."); diff --git a/src/lib/thread/README.md b/src/lib/thread/README.md index ddb5cd6239c..52792d07b3d 100644 --- a/src/lib/thread/README.md +++ b/src/lib/thread/README.md @@ -20,7 +20,7 @@ int main() { ThreadPool &pool = inject(); // preferrably uses constructor injection or setter injection. // Post a task to the thread pool - pool.addLoad([]() { + pool.detach_task([]() { std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl; }); } diff --git a/src/lib/thread/thread_pool.cpp b/src/lib/thread/thread_pool.cpp index 3971d3a6a02..702f0c05504 100644 --- a/src/lib/thread/thread_pool.cpp +++ b/src/lib/thread/thread_pool.cpp @@ -14,84 +14,27 @@ #include "game/game.hpp" #include "utils/tools.hpp" +/** + * Regardless of how many cores your computer have, we want at least + * 4 threads because, even though they won't improve processing they + * will make processing non-blocking in some way and that would allow + * single core computers to process things concurrently, but not in parallel. + */ + #ifndef DEFAULT_NUMBER_OF_THREADS #define DEFAULT_NUMBER_OF_THREADS 4 #endif ThreadPool::ThreadPool(Logger &logger) : - logger(logger) { + logger(logger), BS::thread_pool(std::max(getNumberOfCores(), DEFAULT_NUMBER_OF_THREADS)) { start(); } void ThreadPool::start() { - logger.info("Setting up thread pool"); - - /** - * Regardless of how many cores your computer have, we want at least - * 4 threads because, even though they won't improve processing they - * will make processing non-blocking in some way and that would allow - * single core computers to process things concurrently, but not in parallel. - */ - nThreads = std::max(static_cast(getNumberOfCores()), DEFAULT_NUMBER_OF_THREADS); - - for (std::size_t i = 0; i < nThreads; ++i) { - threads.emplace_back([this] { ioService.run(); }); - } - - logger.info("Running with {} threads.", threads.size()); + logger.info("Running with {} threads.", get_thread_count()); } void ThreadPool::shutdown() { - if (ioService.stopped()) { - return; - } - + stopped = true; logger.info("Shutting down thread pool..."); - - ioService.stop(); - - std::vector> futures; - for (std::size_t i = 0; i < threads.size(); i++) { - logger.debug("Joining thread {}/{}.", i + 1, threads.size()); - - if (threads[i].joinable()) { - futures.emplace_back(std::async(std::launch::async, [&]() { - threads[i].join(); - })); - } - } - - std::future_status status = std::future_status::timeout; - auto timeout = std::chrono::seconds(5); - auto start = std::chrono::steady_clock::now(); - int tries = 0; - while (status == std::future_status::timeout && std::chrono::steady_clock::now() - start < timeout) { - tries++; - if (tries > 5) { - break; - } - for (auto &future : futures) { - status = future.wait_for(std::chrono::seconds(0)); - if (status != std::future_status::timeout) { - break; - } - } - } -} - -asio::io_context &ThreadPool::getIoContext() { - return ioService; -} - -void ThreadPool::addLoad(const std::function &load) { - asio::post(ioService, [this, load]() { - if (ioService.stopped()) { - if (g_game().getGameState() != GAME_STATE_SHUTDOWN) { - logger.error("Shutting down, cannot execute task."); - } - return; - } - - load(); - }); } diff --git a/src/lib/thread/thread_pool.hpp b/src/lib/thread/thread_pool.hpp index e36d8beca57..ea24d3486cb 100644 --- a/src/lib/thread/thread_pool.hpp +++ b/src/lib/thread/thread_pool.hpp @@ -9,8 +9,9 @@ #pragma once #include "lib/logging/logger.hpp" +#include "BS_thread_pool.hpp" -class ThreadPool { +class ThreadPool : public BS::thread_pool { public: explicit ThreadPool(Logger &logger); @@ -20,12 +21,6 @@ class ThreadPool { void start(); void shutdown(); - asio::io_context &getIoContext(); - void addLoad(const std::function &load); - - uint16_t getNumberOfThreads() const { - return nThreads; - } static int16_t getThreadId() { static std::atomic_int16_t lastId = -1; @@ -39,11 +34,11 @@ class ThreadPool { return id; }; + bool isStopped() const { + return stopped; + } + private: Logger &logger; - asio::io_context ioService; - std::vector threads; - asio::io_context::work work { ioService }; - - uint16_t nThreads = 0; + bool stopped = false; }; diff --git a/src/server/network/webhook/webhook.cpp b/src/server/network/webhook/webhook.cpp index 57d4f607aac..f80ff4e59b3 100644 --- a/src/server/network/webhook/webhook.cpp +++ b/src/server/network/webhook/webhook.cpp @@ -38,7 +38,7 @@ Webhook &Webhook::getInstance() { } void Webhook::run() { - threadPool.addLoad([this] { sendWebhook(); }); + threadPool.detach_task([this] { sendWebhook(); }); g_dispatcher().scheduleEvent( g_configManager().getNumber(DISCORD_WEBHOOK_DELAY_MS, __FUNCTION__), [this] { run(); }, "Webhook::run" ); diff --git a/vcpkg.json b/vcpkg.json index dda054f3774..1f821379bad 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -17,6 +17,7 @@ "pugixml", "spdlog", "zlib", + "bshoshany-thread-pool", { "name": "libmariadb", "features": [ From 5636d549bb5bb7fe2ab960524f5588dc08d9c8bf Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 28 May 2024 21:11:34 -0300 Subject: [PATCH 03/17] fix: clean map in pz (#2661) --- src/map/map.cpp | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/map/map.cpp b/src/map/map.cpp index d4d1c4147b1..173b4fbcc3d 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -695,29 +695,17 @@ uint32_t Map::clean() { ItemVector toRemove; toRemove.reserve(128); - for (const auto &mit : mapSectors) { - for (uint8_t z = 0; z < MAP_MAX_LAYERS; ++z) { - if (const auto &floor = mit.second.getFloor(z)) { - for (auto &tiles : floor->getTiles()) { - for (const auto &[tile, cachedTile] : tiles) { - if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - continue; - } - - TileItemVector* itemList = tile->getItemList(); - if (!itemList) { - continue; - } - - ++qntTiles; - - for (auto it = ItemVector::const_reverse_iterator(itemList->getEndDownItem()), end = ItemVector::const_reverse_iterator(itemList->getBeginDownItem()); it != end; ++it) { - const auto &item = *it; - if (item->isCleanable()) { - toRemove.push_back(item); - } - } - } + + for (const auto &tile : g_game().getTilesToClean()) { + if (!tile) { + continue; + } + + if (const auto items = tile->getItemList()) { + ++qntTiles; + for (const auto &item : *items) { + if (item->isCleanable()) { + toRemove.emplace_back(item); } } } From e0193bbd9b1794dff6744d04a933e9515b2879b9 Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Tue, 28 May 2024 21:22:27 -0300 Subject: [PATCH 04/17] fix: crash on move creature (#2662) Fix #2657 --- src/map/map.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/map/map.cpp b/src/map/map.cpp index 173b4fbcc3d..8b8cebeb539 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -320,13 +320,22 @@ bool Map::placeCreature(const Position ¢erPos, std::shared_ptr cre } void Map::moveCreature(const std::shared_ptr &creature, const std::shared_ptr &newTile, bool forceTeleport /* = false*/) { - auto oldTile = creature->getTile(); + if (!creature || !newTile) { + return; + } - Position oldPos = oldTile->getPosition(); - Position newPos = newTile->getPosition(); + const auto &oldTile = creature->getTile(); + + if (!oldTile) { + return; + } + + const auto &oldPos = oldTile->getPosition(); + const auto &newPos = newTile->getPosition(); const auto &fromZones = oldTile->getZones(); const auto &toZones = newTile->getZones(); + if (auto ret = g_game().beforeCreatureZoneChange(creature, fromZones, toZones); ret != RETURNVALUE_NOERROR) { return; } From 368f9d30dc629f9a78b55b78c00952015cb78a9f Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Wed, 29 May 2024 02:26:19 +0200 Subject: [PATCH 05/17] Add GitHub Workflow: MySQL Schema Checker (#2659) --- .github/workflows/mysql-schema-check.yml | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/mysql-schema-check.yml diff --git a/.github/workflows/mysql-schema-check.yml b/.github/workflows/mysql-schema-check.yml new file mode 100644 index 00000000000..b0291956edc --- /dev/null +++ b/.github/workflows/mysql-schema-check.yml @@ -0,0 +1,43 @@ +--- +name: MySQL Schema Check +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - "schema.sql" + merge_group: + push: + paths: + - "schema.sql" + branches: + - main + +jobs: + mysql-schema-check: + runs-on: ubuntu-latest + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: canary + MYSQL_USER: canary + MYSQL_PASSWORD: canary + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + name: Check + steps: + - name: Checkout repository + uses: actions/checkout@main + - name: 📌 MySQL Start & init & show db + run: | + sudo /etc/init.d/mysql start + mysql -e 'CREATE DATABASE canary;' -uroot -proot + mysql -e "SHOW DATABASES" -uroot -proot + - name: Import Canary Schema + run: | + mysql -uroot -proot canary < schema.sql From 38c2ec359ab5eda18f873922cf49f11e6f8e73ba Mon Sep 17 00:00:00 2001 From: Karin Date: Tue, 28 May 2024 21:26:46 -0300 Subject: [PATCH 06/17] fix: wrong exit position fear feaster (#2654) --- .../scripts/actions/bosses_levers/the_fear_feaster.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-otservbr-global/scripts/actions/bosses_levers/the_fear_feaster.lua b/data-otservbr-global/scripts/actions/bosses_levers/the_fear_feaster.lua index af870accd41..41dfa1ffe33 100644 --- a/data-otservbr-global/scripts/actions/bosses_levers/the_fear_feaster.lua +++ b/data-otservbr-global/scripts/actions/bosses_levers/the_fear_feaster.lua @@ -15,7 +15,7 @@ local config = { from = Position(33705, 31463, 14), to = Position(33719, 31477, 14), }, - exit = Position(33609, 31499, 10), + exit = Position(33609, 31495, 10), } local lever = BossLever(config) From e3fefe824ce825cd96bb20d6a418ddfcdb81ff66 Mon Sep 17 00:00:00 2001 From: Karin Date: Wed, 29 May 2024 09:21:37 -0300 Subject: [PATCH 07/17] fix: adding the correct range (#2663) --- .../globalevents/quests/secret_library_preceptor_lazare.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-otservbr-global/scripts/globalevents/quests/secret_library_preceptor_lazare.lua b/data-otservbr-global/scripts/globalevents/quests/secret_library_preceptor_lazare.lua index 4da496fb659..ea05353ad09 100644 --- a/data-otservbr-global/scripts/globalevents/quests/secret_library_preceptor_lazare.lua +++ b/data-otservbr-global/scripts/globalevents/quests/secret_library_preceptor_lazare.lua @@ -1,7 +1,7 @@ local config = { monsterName = "Preceptor Lazare", bossPosition = Position(33374, 31338, 3), - range = 5, + range = 50, } local preceptorLazare = GlobalEvent("PreceptorLazareRespawn") From 6fed1764a943b6034cdbf0428f2bb87ae63efde8 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Wed, 29 May 2024 17:08:03 -0300 Subject: [PATCH 08/17] fix: schema query (#2664) --- data-otservbr-global/migrations/45.lua | 10 ++--- schema.sql | 62 +++++++++++++------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/data-otservbr-global/migrations/45.lua b/data-otservbr-global/migrations/45.lua index c606f18522e..4ceb5f7e3fd 100644 --- a/data-otservbr-global/migrations/45.lua +++ b/data-otservbr-global/migrations/45.lua @@ -3,7 +3,7 @@ function onUpdateDatabase() db.query([[ CREATE TABLE IF NOT EXISTS `account_vipgroups` ( - `id` tinyint(3) UNSIGNED NOT NULL, + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `account_id` int(11) UNSIGNED NOT NULL COMMENT 'id of account whose vip group entry it is', `name` varchar(128) NOT NULL, `customizable` BOOLEAN NOT NULL DEFAULT '1', @@ -13,9 +13,9 @@ function onUpdateDatabase() db.query([[ CREATE TRIGGER `oncreate_accounts` AFTER INSERT ON `accounts` FOR EACH ROW BEGIN - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (1, NEW.`id`, 'Enemies', 0); - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (2, NEW.`id`, 'Friends', 0); - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (3, NEW.`id`, 'Trading Partner', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Enemies', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Friends', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Trading Partner', 0); END; ]]) @@ -23,7 +23,7 @@ function onUpdateDatabase() CREATE TABLE IF NOT EXISTS `account_vipgrouplist` ( `account_id` int(11) UNSIGNED NOT NULL COMMENT 'id of account whose viplist entry it is', `player_id` int(11) NOT NULL COMMENT 'id of target player of viplist entry', - `vipgroup_id` tinyint(3) UNSIGNED NOT NULL COMMENT 'id of vip group that player belongs', + `vipgroup_id` int(11) UNSIGNED NOT NULL COMMENT 'id of vip group that player belongs', INDEX `account_id` (`account_id`), INDEX `player_id` (`player_id`), INDEX `vipgroup_id` (`vipgroup_id`), diff --git a/schema.sql b/schema.sql index bf37d1c2f37..2fbc7dd649b 100644 --- a/schema.sql +++ b/schema.sql @@ -217,7 +217,7 @@ CREATE TABLE IF NOT EXISTS `account_viplist` ( -- Table structure `account_vipgroup` CREATE TABLE IF NOT EXISTS `account_vipgroups` ( - `id` tinyint(3) UNSIGNED NOT NULL, + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `account_id` int(11) UNSIGNED NOT NULL COMMENT 'id of account whose vip group entry it is', `name` varchar(128) NOT NULL, `customizable` BOOLEAN NOT NULL DEFAULT '1', @@ -229,9 +229,9 @@ CREATE TABLE IF NOT EXISTS `account_vipgroups` ( -- DELIMITER // CREATE TRIGGER `oncreate_accounts` AFTER INSERT ON `accounts` FOR EACH ROW BEGIN - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (1, NEW.`id`, 'Enemies', 0); - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (2, NEW.`id`, 'Friends', 0); - INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) VALUES (3, NEW.`id`, 'Trading Partner', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Enemies', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Friends', 0); + INSERT INTO `account_vipgroups` (`account_id`, `name`, `customizable`) VALUES (NEW.`id`, 'Trading Partner', 0); END // DELIMITER ; @@ -240,7 +240,7 @@ DELIMITER ; CREATE TABLE IF NOT EXISTS `account_vipgrouplist` ( `account_id` int(11) UNSIGNED NOT NULL COMMENT 'id of account whose viplist entry it is', `player_id` int(11) NOT NULL COMMENT 'id of target player of viplist entry', - `vipgroup_id` tinyint(3) UNSIGNED NOT NULL COMMENT 'id of vip group that player belongs', + `vipgroup_id` int(11) UNSIGNED NOT NULL COMMENT 'id of vip group that player belongs', INDEX `account_id` (`account_id`), INDEX `player_id` (`player_id`), INDEX `vipgroup_id` (`vipgroup_id`), @@ -258,35 +258,36 @@ CREATE TABLE IF NOT EXISTS `boosted_boss` ( `boostname` TEXT, `date` varchar(250) NOT NULL DEFAULT '', `raceid` varchar(250) NOT NULL DEFAULT '', - `looktypeEx` int(11) NOT NULL DEFAULT "0", - `looktype` int(11) NOT NULL DEFAULT "136", - `lookfeet` int(11) NOT NULL DEFAULT "0", - `looklegs` int(11) NOT NULL DEFAULT "0", - `lookhead` int(11) NOT NULL DEFAULT "0", - `lookbody` int(11) NOT NULL DEFAULT "0", - `lookaddons` int(11) NOT NULL DEFAULT "0", - `lookmount` int(11) DEFAULT "0", + `looktypeEx` int(11) NOT NULL DEFAULT 0, + `looktype` int(11) NOT NULL DEFAULT 136, + `lookfeet` int(11) NOT NULL DEFAULT 0, + `looklegs` int(11) NOT NULL DEFAULT 0, + `lookhead` int(11) NOT NULL DEFAULT 0, + `lookbody` int(11) NOT NULL DEFAULT 0, + `lookaddons` int(11) NOT NULL DEFAULT 0, + `lookmount` int(11) DEFAULT 0, PRIMARY KEY (`date`) -) AS SELECT 0 AS date, "default" AS boostname, 0 AS raceid; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `boosted_boss` (`boostname`, `date`, `raceid`) VALUES ('default', 0, 0); -- Table structure `boosted_creature` CREATE TABLE IF NOT EXISTS `boosted_creature` ( `boostname` TEXT, `date` varchar(250) NOT NULL DEFAULT '', `raceid` varchar(250) NOT NULL DEFAULT '', - `looktype` int(11) NOT NULL DEFAULT "136", - `lookfeet` int(11) NOT NULL DEFAULT "0", - `looklegs` int(11) NOT NULL DEFAULT "0", - `lookhead` int(11) NOT NULL DEFAULT "0", - `lookbody` int(11) NOT NULL DEFAULT "0", - `lookaddons` int(11) NOT NULL DEFAULT "0", - `lookmount` int(11) DEFAULT "0", + `looktype` int(11) NOT NULL DEFAULT 136, + `lookfeet` int(11) NOT NULL DEFAULT 0, + `looklegs` int(11) NOT NULL DEFAULT 0, + `lookhead` int(11) NOT NULL DEFAULT 0, + `lookbody` int(11) NOT NULL DEFAULT 0, + `lookaddons` int(11) NOT NULL DEFAULT 0, + `lookmount` int(11) DEFAULT 0, PRIMARY KEY (`date`) -) AS SELECT 0 AS date, "default" AS boostname, 0 AS raceid; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- -------------------------------------------------------- +INSERT INTO `boosted_creature` (`boostname`, `date`, `raceid`) VALUES ('default', 0, 0); --- -- Tabble Structure `daily_reward_history` CREATE TABLE IF NOT EXISTS `daily_reward_history` ( `id` int(11) NOT NULL AUTO_INCREMENT, @@ -473,7 +474,6 @@ END DELIMITER ; -- Table structure `house_lists` - CREATE TABLE IF NOT EXISTS `house_lists` ( `house_id` int NOT NULL, `listid` int NOT NULL, @@ -485,7 +485,6 @@ CREATE TABLE IF NOT EXISTS `house_lists` ( CONSTRAINT `houses_list_house_fk` FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; - -- Table structure `ip_bans` CREATE TABLE IF NOT EXISTS `ip_bans` ( `ip` int(11) NOT NULL, @@ -540,7 +539,6 @@ CREATE TABLE IF NOT EXISTS `market_offers` ( ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -- Table structure `players_online` CREATE TABLE IF NOT EXISTS `players_online` ( `player_id` int(11) NOT NULL, @@ -671,7 +669,6 @@ CREATE TABLE IF NOT EXISTS `player_wheeldata` ( PRIMARY KEY (`player_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -- Table structure `player_kills` CREATE TABLE IF NOT EXISTS `player_kills` ( `player_id` int(11) NOT NULL, @@ -830,6 +827,7 @@ CREATE TABLE IF NOT EXISTS `account_sessions` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- Table structure `kv_store` CREATE TABLE IF NOT EXISTS `kv_store` ( `key_name` varchar(191) NOT NULL, `timestamp` bigint NOT NULL, @@ -854,7 +852,7 @@ INSERT INTO `players` (6, 'GOD', 6, 1, 2, 0, 155, 155, 100, 113, 115, 95, 39, 75, 0, 60, 60, 0, 8, '', 410, 1, 10, 0, 10, 0, 10, 0, 10, 0); -- Create vip groups for GOD account -INSERT INTO `account_vipgroups` (`id`, `name`, `account_id`, `customizable`) VALUES -(1, 'Friends', 1, 0), -(2, 'Enemies', 1, 0), -(3, 'Trading Partners', 1, 0); +INSERT INTO `account_vipgroups` (`name`, `account_id`, `customizable`) VALUES +('Friends', 1, 0), +('Enemies', 1, 0), +('Trading Partners', 1, 0); From 83ebce55a86dcd31ebd89c301822f8af0daa2d98 Mon Sep 17 00:00:00 2001 From: Karin Date: Sat, 1 Jun 2024 01:44:39 -0300 Subject: [PATCH 09/17] fix: checking if the item is container in playerBuyItem (#2672) --- src/game/game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 621e3593816..899a89549d9 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -5165,7 +5165,7 @@ void Game::playerBuyItem(uint32_t playerId, uint16_t itemId, uint8_t count, uint return; } - if (inBackpacks) { + if (inBackpacks || it.isContainer()) { uint32_t maxContainer = static_cast(g_configManager().getNumber(MAX_CONTAINER, __FUNCTION__)); auto backpack = player->getInventoryItem(CONST_SLOT_BACKPACK); auto mainBackpack = backpack ? backpack->getContainer() : nullptr; From 7e7a6109f521e87bcd82296ee570fff62d7a66c1 Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 1 Jun 2024 14:41:18 -0300 Subject: [PATCH 10/17] refactor: experience calculation efficiency and increase level cap (#2631) --- data/scripts/talkactions/god/add_skill.lua | 7 +------ src/creatures/players/player.hpp | 5 ++--- src/lua/functions/core/game/game_functions.cpp | 11 +++++++++++ src/lua/functions/core/game/game_functions.hpp | 2 ++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/data/scripts/talkactions/god/add_skill.lua b/data/scripts/talkactions/god/add_skill.lua index 20644582325..09d240ece4d 100644 --- a/data/scripts/talkactions/god/add_skill.lua +++ b/data/scripts/talkactions/god/add_skill.lua @@ -16,11 +16,6 @@ local function getSkillId(skillName) end end -local function getExpForLevel(level) - level = level - 1 - return ((50 * level * level * level) - (150 * level * level) + (400 * level)) / 3 -end - local addSkill = TalkAction("/addskill") function addSkill.onSay(player, words, param) @@ -54,7 +49,7 @@ function addSkill.onSay(player, words, param) local ch = split[2]:sub(1, 1) if ch == "l" or ch == "e" then targetLevel = target:getLevel() + count - targetExp = getExpForLevel(targetLevel) + targetExp = Game.getExperienceForLevel(targetLevel) addExp = targetExp - target:getExperience() target:addExperience(addExp, false) elseif ch == "m" then diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 58bebfb9f2f..c0761704db4 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -230,9 +230,8 @@ class Player final : public Creature, public Cylinder, public Bankable { void addList() override; void removePlayer(bool displayEffect, bool forced = true); - static uint64_t getExpForLevel(int32_t lv) { - lv--; - return ((50ULL * lv * lv * lv) - (150ULL * lv * lv) + (400ULL * lv)) / 3ULL; + static uint64_t getExpForLevel(const uint32_t level) { + return (((level - 6ULL) * level + 17ULL) * level - 12ULL) / 6ULL * 100ULL; } uint16_t getStaminaMinutes() const { diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index 0fdbc96f4d6..4858b3ab264 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -191,6 +191,17 @@ int GameFunctions::luaGameloadMapChunk(lua_State* L) { return 0; } +int GameFunctions::luaGameGetExperienceForLevel(lua_State* L) { + // Game.getExperienceForLevel(level) + const uint32_t level = getNumber(L, 1); + if (level == 0) { + reportErrorFunc("Level must be greater than 0."); + } else { + lua_pushnumber(L, Player::getExpForLevel(level)); + } + return 1; +} + int GameFunctions::luaGameGetMonsterCount(lua_State* L) { // Game.getMonsterCount() lua_pushnumber(L, g_game().getMonstersOnline()); diff --git a/src/lua/functions/core/game/game_functions.hpp b/src/lua/functions/core/game/game_functions.hpp index 7f3b642e97d..70e81061c9c 100644 --- a/src/lua/functions/core/game/game_functions.hpp +++ b/src/lua/functions/core/game/game_functions.hpp @@ -28,6 +28,7 @@ class GameFunctions final : LuaScriptInterface { 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); @@ -103,6 +104,7 @@ class GameFunctions final : LuaScriptInterface { static int luaGameLoadMap(lua_State* L); static int luaGameloadMapChunk(lua_State* L); + static int luaGameGetExperienceForLevel(lua_State* L); static int luaGameGetMonsterCount(lua_State* L); static int luaGameGetPlayerCount(lua_State* L); static int luaGameGetNpcCount(lua_State* L); From 3b90a6970a7d91c8c58e1faf49a8af40f35a6835 Mon Sep 17 00:00:00 2001 From: Leandro Date: Sat, 1 Jun 2024 15:32:11 -0300 Subject: [PATCH 11/17] feat: place monster spawn with default time if not set correctly (#2671) --- config.lua.dist | 1 + src/config/config_enums.hpp | 1 + src/config/configmanager.cpp | 1 + src/creatures/monsters/spawns/spawn_monster.cpp | 10 +++++++++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/config.lua.dist b/config.lua.dist index 447a90647c2..9d1ed2fa681 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -511,6 +511,7 @@ bossDefaultTimeToFightAgain = 20 * 60 * 60 -- 20 hours bossDefaultTimeToDefeat = 20 * 60 -- 20 minutes -- Monsters +defaultRespawnTime = 60 deSpawnRange = 2 deSpawnRadius = 50 diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index 22043f42525..0e53c97546e 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -50,6 +50,7 @@ enum ConfigKey_t : uint16_t { DATA_DIRECTORY, DAY_KILLS_TO_RED, DEATH_LOSE_PERCENT, + DEFAULT_RESPAWN_TIME, DEFAULT_DESPAWNRADIUS, DEFAULT_DESPAWNRANGE, DEFAULT_PRIORITY, diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index e1345bbac4b..35d2cf3b1be 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -225,6 +225,7 @@ bool ConfigManager::load() { loadIntConfig(L, CRITICALCHANCE, "criticalChance", 10); loadIntConfig(L, DAY_KILLS_TO_RED, "dayKillsToRedSkull", 3); loadIntConfig(L, DEATH_LOSE_PERCENT, "deathLosePercent", -1); + loadIntConfig(L, DEFAULT_RESPAWN_TIME, "defaultRespawnTime", 60); loadIntConfig(L, DEFAULT_DESPAWNRADIUS, "deSpawnRadius", 50); loadIntConfig(L, DEFAULT_DESPAWNRANGE, "deSpawnRange", 2); loadIntConfig(L, DEPOTCHEST, "depotChest", 4); diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp index ef5912c8052..968b90d8cae 100644 --- a/src/creatures/monsters/spawns/spawn_monster.cpp +++ b/src/creatures/monsters/spawns/spawn_monster.cpp @@ -94,7 +94,15 @@ bool SpawnsMonster::loadFromXML(const std::string &filemonstername) { weight = pugi::cast(weightAttribute.value()); } - spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, pugi::cast(childMonsterNode.attribute("spawntime").value()) * 1000, weight); + uint32_t scheduleInterval = g_configManager().getNumber(DEFAULT_RESPAWN_TIME, __FUNCTION__); + + 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); + } + + spawnMonster.addMonster(nameAttribute.as_string(), pos, dir, scheduleInterval * 1000, weight); } } } From 8d74ea6db7c663fdc199fc39be3d137fa685544c Mon Sep 17 00:00:00 2001 From: Renato Machado Date: Sun, 2 Jun 2024 00:02:44 -0300 Subject: [PATCH 12/17] fix: possible memory leak in connection (#2668) May never be called async_wait and therefore may leave the connection stuck in limbo. --- src/server/network/connection/connection.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp index 1c575ff00d0..3effd52f829 100644 --- a/src/server/network/connection/connection.cpp +++ b/src/server/network/connection/connection.cpp @@ -105,7 +105,7 @@ void Connection::accept(Protocol_ptr protocolPtr) { void Connection::acceptInternal(bool toggleParseHeader) { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + readTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); try { asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this(), toggleParseHeader](const std::error_code &error, std::size_t N) { @@ -147,7 +147,7 @@ void Connection::parseProxyIdentification(const std::error_code &error) { connectionState = CONNECTION_STATE_READINGS; try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + readTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); // Read the remainder of proxy identification asio::async_read(socket, asio::buffer(msg.getBuffer(), remainder), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseProxyIdentification(error); }); @@ -208,7 +208,7 @@ void Connection::parseHeader(const std::error_code &error) { try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + readTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); // Read packet content msg.setLength(size + HEADER_LENGTH); @@ -275,7 +275,7 @@ void Connection::parsePacket(const std::error_code &error) { try { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + readTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); if (!skipReadingNextPacket) { // Wait to the next packet @@ -289,7 +289,7 @@ void Connection::parsePacket(const std::error_code &error) { void Connection::resumeWork() { readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + readTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); try { asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseHeader(error); }); @@ -358,7 +358,7 @@ uint32_t Connection::getIP() { void Connection::internalSend(const OutputMessage_ptr &outputMessage) { writeTimer.expires_from_now(std::chrono::seconds(CONNECTION_WRITE_TIMEOUT)); - readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); }); + writeTimer.async_wait([self = std::weak_ptr(shared_from_this())](const std::error_code &error) { Connection::handleTimeout(self, error); }); try { asio::async_write(socket, asio::buffer(outputMessage->getOutputBuffer(), outputMessage->getLength()), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->onWriteOperation(error); }); From 02a7bc0c85c3a9cc0817b59950679a2b355f6c71 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Mon, 3 Jun 2024 15:44:36 -0300 Subject: [PATCH 13/17] feat: equipments winter update 2023 (#2608) --- data/items/items.xml | 290 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/data/items/items.xml b/data/items/items.xml index e7e73d9753b..9fdc89bbd8f 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -75820,5 +75820,295 @@ Granted by TibiaGoals.com"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2db5fee1f44a6d5cadca8db6a9ef9defdbad67f0 Mon Sep 17 00:00:00 2001 From: miah-sebastian Date: Tue, 4 Jun 2024 18:42:36 -0400 Subject: [PATCH 14/17] fix: opentelemetry linker error (#2678) --- vcpkg.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vcpkg.json b/vcpkg.json index 1f821379bad..eed7e776ee0 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -18,6 +18,11 @@ "spdlog", "zlib", "bshoshany-thread-pool", + { + "name": "opentelemetry-cpp", + "default-features": true, + "features": ["otlp-http", "prometheus"] + }, { "name": "libmariadb", "features": [ From 4af13eefdcc71f900587f3f4e9afa8083a1fe1ae Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 4 Jun 2024 22:17:28 -0300 Subject: [PATCH 15/17] fix: small adjustments and corrections to the core (#2524) - Previously, players were not being removed from the room upon killing the boss, as the relevant script was confined to rlmap only. This update ensures its functionality across any datapack. - Hirelings are now accessible beyond rlmap environments. - Addressed an issue with the loading of VIP days library. - Relocated the large sea shell asset to the core. - Implemented VIP status check and associated actions. - Transferred weapons scripts to the core. --- .../scripts/actions/other/large_sea_shell.lua | 28 ----- .../scripts/weapons/scripted_weapons.lua | 101 ------------------ data-otservbr-global/lib/others/load.lua | 1 - .../scripts/creaturescripts/customs/vip.lua | 20 ---- .../creaturescripts/others/forge_kill.lua | 12 --- .../{bosslever.lua => boss_lever.lua} | 0 data/libs/functions/load.lua | 10 +- data/libs/systems/load.lua | 1 + .../libs/systems/vip.lua | 20 ++-- .../scripts/actions/items/hireling_lamp.lua | 7 +- .../actions/objects/large_seashell.lua | 30 ++++++ .../monster/boss_lever_death.lua | 7 ++ .../creaturescripts/monster}/forge_kill.lua | 0 .../player}/adventure_blessing_login.lua | 1 + data/scripts/creaturescripts/player/login.lua | 24 ++++- .../scripts/weapons/dawnport_weapons.lua | 0 .../scripts/weapons/scripts/burst_arrow.lua | 0 .../scripts/weapons/scripts/diamond_arrow.lua | 0 .../scripts/weapons/scripts/poison_arrow.lua | 0 .../scripts/weapons/scripts/viper_star.lua | 0 20 files changed, 75 insertions(+), 187 deletions(-) delete mode 100644 data-canary/scripts/actions/other/large_sea_shell.lua delete mode 100644 data-canary/scripts/weapons/scripted_weapons.lua delete mode 100644 data-otservbr-global/scripts/creaturescripts/customs/vip.lua delete mode 100644 data-otservbr-global/scripts/creaturescripts/others/forge_kill.lua rename data/libs/functions/{bosslever.lua => boss_lever.lua} (100%) rename data-otservbr-global/lib/others/vip_system.lua => data/libs/systems/vip.lua (61%) rename data-otservbr-global/scripts/actions/other/hirelinglamp.lua => data/scripts/actions/items/hireling_lamp.lua (93%) create mode 100644 data/scripts/actions/objects/large_seashell.lua rename data-otservbr-global/scripts/globalevents/others/bosslever_death.lua => data/scripts/creaturescripts/monster/boss_lever_death.lua (99%) rename {data-canary/scripts/creaturescripts => data/scripts/creaturescripts/monster}/forge_kill.lua (100%) rename {data-otservbr-global/scripts/creaturescripts/others => data/scripts/creaturescripts/player}/adventure_blessing_login.lua (99%) rename data-otservbr-global/scripts/weapons/dawnport_weapon.lua => data/scripts/weapons/dawnport_weapons.lua (100%) rename {data-otservbr-global => data}/scripts/weapons/scripts/burst_arrow.lua (100%) rename {data-otservbr-global => data}/scripts/weapons/scripts/diamond_arrow.lua (100%) rename {data-otservbr-global => data}/scripts/weapons/scripts/poison_arrow.lua (100%) rename {data-otservbr-global => data}/scripts/weapons/scripts/viper_star.lua (100%) diff --git a/data-canary/scripts/actions/other/large_sea_shell.lua b/data-canary/scripts/actions/other/large_sea_shell.lua deleted file mode 100644 index b396bd70611..00000000000 --- a/data-canary/scripts/actions/other/large_sea_shell.lua +++ /dev/null @@ -1,28 +0,0 @@ -local largeSeaShell = Action() - -function largeSeaShell.onUse(player, item, fromPosition, target, toPosition, isHotkey) - if player:getStorageValue(Storage.DelayLargeSeaShell) <= os.time() then - local chance = math.random(100) - local msg = "" - if chance <= 16 then - doTargetCombatHealth(0, player, COMBAT_PHYSICALDAMAGE, -200, -200, CONST_ME_NONE) - msg = "Ouch! You squeezed your fingers." - elseif chance > 16 and chance <= 64 then - Game.createItem(math.random(281, 282), 1, player:getPosition()) - msg = "You found a beautiful pearl." - else - msg = "Nothing is inside." - end - player:say(msg, TALKTYPE_MONSTER_SAY, false, player, item:getPosition()) - item:transform(198) - item:decay() - player:setStorageValue(Storage.DelayLargeSeaShell, os.time() + 20 * 60 * 60) - item:getPosition():sendMagicEffect(CONST_ME_BUBBLES) - else - player:say("You have already opened a shell today.", TALKTYPE_MONSTER_SAY, false, player, item:getPosition()) - end - return true -end - -largeSeaShell:id(197) -largeSeaShell:register() diff --git a/data-canary/scripts/weapons/scripted_weapons.lua b/data-canary/scripts/weapons/scripted_weapons.lua deleted file mode 100644 index 93e677d43cd..00000000000 --- a/data-canary/scripts/weapons/scripted_weapons.lua +++ /dev/null @@ -1,101 +0,0 @@ -local burstArea = createCombatArea({ - { 1, 1, 1 }, - { 1, 3, 1 }, - { 1, 1, 1 }, -}) - -local burstCombat = Combat() -burstCombat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -burstCombat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -burstCombat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_BURSTARROW) -burstCombat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -burstCombat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) -burstCombat:setParameter(COMBAT_PARAM_IMPACTSOUND, SOUND_EFFECT_TYPE_BURST_ARROW_EFFECT) -burstCombat:setParameter(COMBAT_PARAM_CASTSOUND, SOUND_EFFECT_TYPE_DIST_ATK_BOW) -burstCombat:setArea(burstArea) - -local burstarrow = Weapon(WEAPON_AMMO) -burstarrow.onUseWeapon = function(player, variant) - if player:getSkull() == SKULL_BLACK then - return false - end - - return burstCombat:execute(player, variant) -end - -burstarrow:id(3449) -burstarrow:action("removecount") -burstarrow:register() - -local poisonCombat = Combat() -poisonCombat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -poisonCombat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISONARROW) -poisonCombat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -poisonCombat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) - -local poisonarrow = Weapon(WEAPON_AMMO) -poisonarrow.onUseWeapon = function(player, variant) - if not poisonCombat:execute(player, variant) then - return false - end - - player:addDamageCondition(Creature(variant:getNumber()), CONDITION_POISON, DAMAGELIST_LOGARITHMIC_DAMAGE, 3) - return true -end - -poisonarrow:id(3448) -poisonarrow:action("removecount") -poisonarrow:register() - -local viperCombat = Combat() -viperCombat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -viperCombat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_GREENSTAR) -viperCombat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -viperCombat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) - -local viperstar = Weapon(WEAPON_DISTANCE) -viperstar.onUseWeapon = function(player, variant) - if not viperCombat:execute(player, variant) then - return false - end - - if math.random(1, 100) <= 90 then - return false - end - - player:addDamageCondition(Creature(variant:getNumber()), CONDITION_POISON, DAMAGELIST_LOGARITHMIC_DAMAGE, 2) - return true -end - -viperstar:id(7366) -viperstar:breakChance(9) -viperstar:register() - -local diamondArea = createCombatArea({ - { 0, 1, 1, 1, 0 }, - { 1, 1, 1, 1, 1 }, - { 1, 1, 3, 1, 1 }, - { 1, 1, 1, 1, 1 }, - { 0, 1, 1, 1, 0 }, -}) - -local diamondCombat = Combat() -diamondCombat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -diamondCombat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -diamondCombat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DIAMONDARROW) -diamondCombat:setParameter(COMBAT_PARAM_IMPACTSOUND, SOUND_EFFECT_TYPE_DIAMOND_ARROW_EFFECT) -diamondCombat:setParameter(COMBAT_PARAM_CASTSOUND, SOUND_EFFECT_TYPE_DIST_ATK_BOW) -diamondCombat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -diamondCombat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) -diamondCombat:setArea(diamondArea) - -local diamondarrow = Weapon(WEAPON_AMMO) -diamondarrow.onUseWeapon = function(player, variant) - return diamondCombat:execute(player, variant) -end - -diamondarrow:id(ITEM_OLD_DIAMOND_ARROW) -diamondarrow:action("removecount") -diamondarrow:level(150) -diamondarrow:wieldUnproperly(true) -diamondarrow:register() diff --git a/data-otservbr-global/lib/others/load.lua b/data-otservbr-global/lib/others/load.lua index 1052efb7bd6..031c8fb2026 100644 --- a/data-otservbr-global/lib/others/load.lua +++ b/data-otservbr-global/lib/others/load.lua @@ -1,2 +1 @@ dofile(DATA_DIRECTORY .. "/lib/others/dawnport.lua") -dofile(DATA_DIRECTORY .. "/lib/others/vip_system.lua") diff --git a/data-otservbr-global/scripts/creaturescripts/customs/vip.lua b/data-otservbr-global/scripts/creaturescripts/customs/vip.lua deleted file mode 100644 index 0ae99c00f2d..00000000000 --- a/data-otservbr-global/scripts/creaturescripts/customs/vip.lua +++ /dev/null @@ -1,20 +0,0 @@ -local playerLogin = CreatureEvent("VipLogin") - -function playerLogin.onLogin(player) - if configManager.getBoolean(configKeys.VIP_SYSTEM_ENABLED) then - local wasVip = player:kv():scoped("account"):get("vip-system") or false - if wasVip and not player:isVip() then - player:onRemoveVip() - end - if not wasVip and player:isVip() then - player:onAddVip(player:getVipDays()) - end - - if player:isVip() then - CheckPremiumAndPrint(player, MESSAGE_LOGIN) - end - end - return true -end - -playerLogin:register() diff --git a/data-otservbr-global/scripts/creaturescripts/others/forge_kill.lua b/data-otservbr-global/scripts/creaturescripts/others/forge_kill.lua deleted file mode 100644 index 3e454d84d14..00000000000 --- a/data-otservbr-global/scripts/creaturescripts/others/forge_kill.lua +++ /dev/null @@ -1,12 +0,0 @@ -local forgeKill = CreatureEvent("ForgeSystemMonster") - -function forgeKill.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) - local targetMonster = creature:getMonster() - if not targetMonster then - return true - end - - return ForgeMonster:onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) -end - -forgeKill:register() diff --git a/data/libs/functions/bosslever.lua b/data/libs/functions/boss_lever.lua similarity index 100% rename from data/libs/functions/bosslever.lua rename to data/libs/functions/boss_lever.lua diff --git a/data/libs/functions/load.lua b/data/libs/functions/load.lua index c63276d9444..0fab2c3cb5e 100644 --- a/data/libs/functions/load.lua +++ b/data/libs/functions/load.lua @@ -1,14 +1,15 @@ -- Load core functions dofile(CORE_DIRECTORY .. "/libs/functions/bit.lua") dofile(CORE_DIRECTORY .. "/libs/functions/bitwise_flags.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/boss_lever.lua") dofile(CORE_DIRECTORY .. "/libs/functions/combat.lua") dofile(CORE_DIRECTORY .. "/libs/functions/constants.lua") dofile(CORE_DIRECTORY .. "/libs/functions/container.lua") dofile(CORE_DIRECTORY .. "/libs/functions/creature.lua") -dofile(CORE_DIRECTORY .. "/libs/functions/functions.lua") -dofile(CORE_DIRECTORY .. "/libs/functions/gematelier.lua") dofile(CORE_DIRECTORY .. "/libs/functions/fs.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/functions.lua") dofile(CORE_DIRECTORY .. "/libs/functions/game.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/gematelier.lua") dofile(CORE_DIRECTORY .. "/libs/functions/item.lua") dofile(CORE_DIRECTORY .. "/libs/functions/itemtype.lua") dofile(CORE_DIRECTORY .. "/libs/functions/lever.lua") @@ -20,14 +21,13 @@ dofile(CORE_DIRECTORY .. "/libs/functions/player.lua") dofile(CORE_DIRECTORY .. "/libs/functions/position.lua") dofile(CORE_DIRECTORY .. "/libs/functions/pronouns.lua") dofile(CORE_DIRECTORY .. "/libs/functions/quests.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/queue.lua") dofile(CORE_DIRECTORY .. "/libs/functions/revscriptsys.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/set.lua") dofile(CORE_DIRECTORY .. "/libs/functions/spawn.lua") dofile(CORE_DIRECTORY .. "/libs/functions/spectators.lua") -dofile(CORE_DIRECTORY .. "/libs/functions/bosslever.lua") dofile(CORE_DIRECTORY .. "/libs/functions/string.lua") dofile(CORE_DIRECTORY .. "/libs/functions/tables.lua") dofile(CORE_DIRECTORY .. "/libs/functions/teleport.lua") dofile(CORE_DIRECTORY .. "/libs/functions/tile.lua") dofile(CORE_DIRECTORY .. "/libs/functions/vocation.lua") -dofile(CORE_DIRECTORY .. "/libs/functions/set.lua") -dofile(CORE_DIRECTORY .. "/libs/functions/queue.lua") diff --git a/data/libs/systems/load.lua b/data/libs/systems/load.lua index 5c7073ad64e..281b8b1d466 100644 --- a/data/libs/systems/load.lua +++ b/data/libs/systems/load.lua @@ -9,4 +9,5 @@ dofile(CORE_DIRECTORY .. "/libs/systems/hazard.lua") dofile(CORE_DIRECTORY .. "/libs/systems/hireling.lua") dofile(CORE_DIRECTORY .. "/libs/systems/raids.lua") dofile(CORE_DIRECTORY .. "/libs/systems/reward_boss.lua") +dofile(CORE_DIRECTORY .. "/libs/systems/vip.lua") dofile(CORE_DIRECTORY .. "/libs/systems/zones.lua") diff --git a/data-otservbr-global/lib/others/vip_system.lua b/data/libs/systems/vip.lua similarity index 61% rename from data-otservbr-global/lib/others/vip_system.lua rename to data/libs/systems/vip.lua index 5a393157c8c..9e76fd8ad80 100644 --- a/data-otservbr-global/lib/others/vip_system.lua +++ b/data/libs/systems/vip.lua @@ -1,16 +1,10 @@ local config = { - activationMessage = "You have received %s VIP days.", - activationMessageType = MESSAGE_EVENT_ADVANCE, - - expirationMessage = "Your VIP days ran out.", - expirationMessageType = MESSAGE_ADMINISTRATOR, - outfits = {}, mounts = {}, } function Player.onRemoveVip(self) - self:sendTextMessage(config.expirationMessageType, config.expirationMessage) + self:sendTextMessage(MESSAGE_ADMINISTRATOR, "Your VIP status has expired. All VIP benefits have been removed.") for _, outfit in ipairs(config.outfits) do self:removeOutfit(outfit) @@ -21,13 +15,14 @@ function Player.onRemoveVip(self) end local playerOutfit = self:getOutfit() - if table.contains(config.outfits, self:getOutfit().lookType) then + if table.contains(config.outfits, playerOutfit.lookType) then if self:getSex() == PLAYERSEX_FEMALE then playerOutfit.lookType = 136 else playerOutfit.lookType = 128 end playerOutfit.lookAddons = 0 + self:setOutfit(playerOutfit) end @@ -36,7 +31,7 @@ end function Player.onAddVip(self, days, silent) if not silent then - self:sendTextMessage(config.activationMessageType, string.format(config.activationMessage, days)) + self:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You have been granted %s days of VIP status.", days)) end for _, outfit in ipairs(config.outfits) do @@ -52,16 +47,15 @@ end function CheckPremiumAndPrint(player, msgType) if player:getVipDays() == 0xFFFF then - player:sendTextMessage(msgType, "You have infinite amount of VIP days left.") + player:sendTextMessage(msgType, "You have an unlimited VIP status.") return true end local playerVipTime = player:getVipTime() if playerVipTime < os.time() then - local msg = "You do not have VIP on your account." - player:sendTextMessage(msgType, msg) + player:sendTextMessage(msgType, "Your VIP status is currently inactive.") return true end - player:sendTextMessage(msgType, string.format("You have %s of VIP time left.", getFormattedTimeRemaining(playerVipTime))) + player:sendTextMessage(msgType, string.format("You have %s of VIP time remaining.", getFormattedTimeRemaining(playerVipTime))) end diff --git a/data-otservbr-global/scripts/actions/other/hirelinglamp.lua b/data/scripts/actions/items/hireling_lamp.lua similarity index 93% rename from data-otservbr-global/scripts/actions/other/hirelinglamp.lua rename to data/scripts/actions/items/hireling_lamp.lua index 8117b5366bc..0ffed1fa744 100644 --- a/data-otservbr-global/scripts/actions/other/hirelinglamp.lua +++ b/data/scripts/actions/items/hireling_lamp.lua @@ -2,8 +2,9 @@ local hirelingLamp = Action() function hirelingLamp.onUse(player, item, fromPosition, target, toPosition, isHotkey) local spawnPosition = player:getPosition() - local hireling_id = item:getCustomAttribute("Hireling") + local hirelingId = item:getCustomAttribute("Hireling") local house = spawnPosition and spawnPosition:getTile() and spawnPosition:getTile():getHouse() or nil + if not house then player:getPosition():sendMagicEffect(CONST_ME_POFF) player:sendTextMessage(MESSAGE_FAILURE, "You may use this only inside a house.") @@ -22,10 +23,10 @@ function hirelingLamp.onUse(player, item, fromPosition, target, toPosition, isHo return false end - local hireling = getHirelingById(hireling_id) + local hireling = getHirelingById(hirelingId) if not hireling then player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "There was an error creating the hireling and it has been deleted, please, contact server admin.") - logger.warn("[hirelingLamp.onUse] Player {} is using hireling with id {} not exist in the database", player:getName(), hireling_id) + logger.warn("[hirelingLamp.onUse] Player {} is using hireling with id {} not exist in the database", player:getName(), hirelingId) logger.error("Deleted the lamp") item:remove(1) return true diff --git a/data/scripts/actions/objects/large_seashell.lua b/data/scripts/actions/objects/large_seashell.lua new file mode 100644 index 00000000000..c6d767146ec --- /dev/null +++ b/data/scripts/actions/objects/large_seashell.lua @@ -0,0 +1,30 @@ +local largeSeashell = Action() + +function largeSeashell.onUse(player, item, fromPosition, target, toPosition, isHotkey) + if player:hasExhaustion("delay-large-seashell") then + player:say("You have already opened a shell today.", TALKTYPE_MONSTER_SAY, false, player, item:getPosition()) + return true + end + + local chance = math.random(100) + local message = "Nothing is inside." + + if chance <= 16 then + doTargetCombatHealth(0, player, COMBAT_PHYSICALDAMAGE, -200, -200, CONST_ME_NONE) + message = "Ouch! You squeezed your fingers." + elseif chance > 16 and chance <= 64 then + Game.createItem(math.random(281, 282), 1, player:getPosition()) + message = "You found a beautiful pearl." + player:addAchievementProgress("Shell Seeker", 100) + end + + player:setExhaustion("delay-large-seashell", 20 * 60 * 60) + player:say(message, TALKTYPE_MONSTER_SAY, false, player, item:getPosition()) + item:transform(198) + item:decay() + item:getPosition():sendMagicEffect(CONST_ME_BUBBLES) + return true +end + +largeSeashell:id(197) +largeSeashell:register() diff --git a/data-otservbr-global/scripts/globalevents/others/bosslever_death.lua b/data/scripts/creaturescripts/monster/boss_lever_death.lua similarity index 99% rename from data-otservbr-global/scripts/globalevents/others/bosslever_death.lua rename to data/scripts/creaturescripts/monster/boss_lever_death.lua index 9538fe15eb7..a2c58d1e43b 100644 --- a/data-otservbr-global/scripts/globalevents/others/bosslever_death.lua +++ b/data/scripts/creaturescripts/monster/boss_lever_death.lua @@ -1,22 +1,28 @@ local onBossDeath = CreatureEvent("BossLeverOnDeath") + function onBossDeath.onDeath(creature) if not creature then return true end + local name = creature:getName() local key = "boss." .. toKey(name) local zone = Zone(key) + if not zone then return true end + local bossLever = BossLever[name] if not bossLever then return true end + if bossLever.timeoutEvent then stopEvent(bossLever.timeoutEvent) bossLever.timeoutEvent = nil end + if bossLever.timeAfterKill > 0 then zone:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The " .. name .. " has been defeated. You have " .. bossLever.timeAfterKill .. " seconds to leave the room.") bossLever.timeoutEvent = addEvent(function(zn) @@ -26,4 +32,5 @@ function onBossDeath.onDeath(creature) end return true end + onBossDeath:register() diff --git a/data-canary/scripts/creaturescripts/forge_kill.lua b/data/scripts/creaturescripts/monster/forge_kill.lua similarity index 100% rename from data-canary/scripts/creaturescripts/forge_kill.lua rename to data/scripts/creaturescripts/monster/forge_kill.lua diff --git a/data-otservbr-global/scripts/creaturescripts/others/adventure_blessing_login.lua b/data/scripts/creaturescripts/player/adventure_blessing_login.lua similarity index 99% rename from data-otservbr-global/scripts/creaturescripts/others/adventure_blessing_login.lua rename to data/scripts/creaturescripts/player/adventure_blessing_login.lua index df04052716f..8ebf88a72e9 100644 --- a/data-otservbr-global/scripts/creaturescripts/others/adventure_blessing_login.lua +++ b/data/scripts/creaturescripts/player/adventure_blessing_login.lua @@ -1,6 +1,7 @@ dofile(CORE_DIRECTORY .. "/modules/scripts/blessings/blessings.lua") local adventurerBlessingLogin = CreatureEvent("AdventurerBlessingLogin") + function adventurerBlessingLogin.onLogin(player) return Blessings.doAdventurerBlessing(player) end diff --git a/data/scripts/creaturescripts/player/login.lua b/data/scripts/creaturescripts/player/login.lua index 34d139a047d..fbe4f9e63b6 100644 --- a/data/scripts/creaturescripts/player/login.lua +++ b/data/scripts/creaturescripts/player/login.lua @@ -49,10 +49,8 @@ function playerLoginGlobal.onLogin(player) end -- Boosted - player:sendTextMessage(MESSAGE_BOOSTED_CREATURE, "Today's boosted creature: " .. Game.getBoostedCreature() .. " \ - Boosted creatures yield more experience points, carry more loot than usual and respawn at a faster rate.") - player:sendTextMessage(MESSAGE_BOOSTED_CREATURE, "Today's boosted boss: " .. Game.getBoostedBoss() .. " \ - Boosted bosses contain more loot and count more kills for your Bosstiary.") + player:sendTextMessage(MESSAGE_BOOSTED_CREATURE, string.format("Today's boosted creature: %s.\nBoosted creatures yield more experience points, carry more loot than usual, and respawn at a faster rate.", Game.getBoostedCreature())) + player:sendTextMessage(MESSAGE_BOOSTED_CREATURE, string.format("Today's boosted boss: %s.\nBoosted bosses contain more loot and count more kills for your Bosstiary.", Game.getBoostedBoss())) -- Rewards local rewards = #player:getRewardList() @@ -118,6 +116,24 @@ function playerLoginGlobal.onLogin(player) player:setStaminaXpBoost(player:getFinalBonusStamina() * 100) player:getFinalLowLevelBonus() + -- 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 + + if wasVip ~= isVipNow then + if wasVip then + player:onRemoveVip() + else + player:onAddVip(player:getVipDays()) + end + end + + if isVipNow then + CheckPremiumAndPrint(player, MESSAGE_LOGIN) + end + end + -- Set Ghost Mode if player:getGroup():getId() >= GROUP_TYPE_GAMEMASTER then player:setGhostMode(true) diff --git a/data-otservbr-global/scripts/weapons/dawnport_weapon.lua b/data/scripts/weapons/dawnport_weapons.lua similarity index 100% rename from data-otservbr-global/scripts/weapons/dawnport_weapon.lua rename to data/scripts/weapons/dawnport_weapons.lua diff --git a/data-otservbr-global/scripts/weapons/scripts/burst_arrow.lua b/data/scripts/weapons/scripts/burst_arrow.lua similarity index 100% rename from data-otservbr-global/scripts/weapons/scripts/burst_arrow.lua rename to data/scripts/weapons/scripts/burst_arrow.lua diff --git a/data-otservbr-global/scripts/weapons/scripts/diamond_arrow.lua b/data/scripts/weapons/scripts/diamond_arrow.lua similarity index 100% rename from data-otservbr-global/scripts/weapons/scripts/diamond_arrow.lua rename to data/scripts/weapons/scripts/diamond_arrow.lua diff --git a/data-otservbr-global/scripts/weapons/scripts/poison_arrow.lua b/data/scripts/weapons/scripts/poison_arrow.lua similarity index 100% rename from data-otservbr-global/scripts/weapons/scripts/poison_arrow.lua rename to data/scripts/weapons/scripts/poison_arrow.lua diff --git a/data-otservbr-global/scripts/weapons/scripts/viper_star.lua b/data/scripts/weapons/scripts/viper_star.lua similarity index 100% rename from data-otservbr-global/scripts/weapons/scripts/viper_star.lua rename to data/scripts/weapons/scripts/viper_star.lua From 8af607bdf87ab8004ed01e9557175f2d33116eec Mon Sep 17 00:00:00 2001 From: Paulo Henrique Lisboa Date: Tue, 11 Jun 2024 10:05:04 -0300 Subject: [PATCH 16/17] fix: docker ubuntu package and start.sh permission (#2681) --- docker/Dockerfile.dev | 6 +++--- docker/data/start.sh | 4 ++-- docker/docker-compose.yml | 2 -- start.sh | 0 4 files changed, 5 insertions(+), 7 deletions(-) mode change 100644 => 100755 start.sh diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index 161a80a2e21..4cd63334d5e 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,10 +1,10 @@ # Stage 1: Download all dependencies -FROM ubuntu:23.04 AS dependencies +FROM ubuntu:24.04 AS dependencies RUN --mount=type=cache,target=/var/cache/apt \ apt-get update && apt-get install -y --no-install-recommends cmake git \ unzip build-essential ca-certificates curl zip unzip tar \ - pkg-config ninja-build autoconf automake libtool \ + pkg-config ninja-build autoconf automake libtool glibc-tools \ python3 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* @@ -32,7 +32,7 @@ COPY recompile.sh CMakeLists.txt CMakePresets.json vcpkg.json ./ RUN ./recompile.sh "/opt" # Stage 3: execute -FROM ubuntu:23.04 AS prod +FROM ubuntu:24.04 AS prod COPY --from=build /srv/build/build/linux-release/bin/canary /bin/canary WORKDIR /srv/canary ENTRYPOINT ["/srv/canary/start.sh", "canary"] diff --git a/docker/data/start.sh b/docker/data/start.sh index db688b488d0..c7d10fa0fdb 100755 --- a/docker/data/start.sh +++ b/docker/data/start.sh @@ -10,8 +10,8 @@ OT_SERVER_LOGIN_PORT="${OT_SERVER_LOGIN_PORT:-7171}" OT_SERVER_GAME_PORT="${OT_SERVER_GAME_PORT:-7172}" OT_SERVER_STATUS_PORT="${OT_SERVER_STATUS_PORT:-7171}" OT_SERVER_TEST_ACCOUNTS="${OT_SERVER_TEST_ACCOUNTS:-false}" -OT_SERVER_DATA="${OT_SERVER_DATA:-data-canary}" -OT_SERVER_MAP="${OT_SERVER_MAP:-https://github.com/opentibiabr/otservbr-global/releases/download/v1.5.0/otservbr.otbm}" +OT_SERVER_DATA="${OT_SERVER_DATA:-data-otservbr-global}" +OT_SERVER_MAP="${OT_SERVER_MAP:-https://github.com/opentibiabr/canary/releases/download/v3.1.0/otservbr.otbm}" echo "" echo "===== Print Variables =====" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 46a2fb619b2..88fd938e500 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,3 @@ ---- -version: '3.8' name: otbr services: database: diff --git a/start.sh b/start.sh old mode 100644 new mode 100755 From ede4b035bcb3c664bd42c757f1d4466b8d7b5c43 Mon Sep 17 00:00:00 2001 From: Felipe Paluco <87909998+FelipePaluco@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:05:20 -0300 Subject: [PATCH 17/17] feat: rebalancing monsters (#2683) --- data-canary/monster/demons/fury.lua | 2 +- data-canary/monster/demons/juggernaut.lua | 4 ++-- .../monster/aquatics/quara_constrictor.lua | 2 +- .../monster/aquatics/quara_hydromancer.lua | 2 +- .../monster/aquatics/quara_mantassin.lua | 2 +- .../monster/aquatics/quara_pincher.lua | 2 +- .../monster/aquatics/quara_predator.lua | 2 +- data-otservbr-global/monster/bosses/splasher.lua | 2 +- .../monster/constructs/clay_guardian.lua | 2 +- .../monster/constructs/infected_weeper.lua | 2 +- .../monster/constructs/lava_golem.lua | 3 +-- .../monster/constructs/magma_crawler.lua | 8 ++++---- .../monster/constructs/orewalker.lua | 3 +-- .../monster/constructs/stone_devourer.lua | 2 +- data-otservbr-global/monster/constructs/weeper.lua | 6 +++--- .../monster/demons/hellfire_fighter.lua | 2 +- .../monster/elementals/cliff_strider.lua | 6 +++--- .../monster/elementals/earth_elemental.lua | 4 ++-- .../monster/elementals/high_voltage_elemental.lua | 2 +- .../monster/elementals/ironblight.lua | 2 +- .../monster/elementals/massive_earth_elemental.lua | 4 ++-- .../monster/elementals/sulphur_spouter.lua | 2 +- .../monster/humanoids/lost_basher.lua | 6 +++--- .../monster/humanoids/lost_berserker.lua | 12 +++++------- .../monster/humanoids/lost_husher.lua | 9 ++++----- .../monster/humanoids/lost_thrower.lua | 6 +++--- data-otservbr-global/monster/magicals/armadile.lua | 13 +++++-------- .../monster/magicals/choking_fear.lua | 2 +- data-otservbr-global/monster/magicals/phantasm.lua | 2 +- .../monster/magicals/retching_horror.lua | 2 +- .../monster/mammals/mutated_bat.lua | 2 +- .../monster/plants/hideous_fungus.lua | 13 ++++++------- .../monster/plants/humongous_fungus.lua | 7 +++---- .../quests/bigfoots_burden/bosses/abyssador.lua | 2 +- .../quests/bigfoots_burden/bosses/gnomevil.lua | 2 +- .../quests/bigfoots_burden/humorless_fungus.lua | 9 +++------ .../bosses/the_count_of_the_core.lua | 2 +- .../bosses/the_duke_of_the_depths.lua | 2 +- .../bosses/ferumbras_mortal_shell.lua | 2 +- .../quests/ferumbras_ascendant/bosses/mazoran.lua | 2 +- .../quests/ferumbras_ascendant/bosses/plagirath.lua | 2 +- .../quests/ferumbras_ascendant/bosses/ragiaz.lua | 2 +- .../quests/ferumbras_ascendant/bosses/razzagorn.lua | 2 +- .../quests/ferumbras_ascendant/bosses/shulgrax.lua | 2 +- .../quests/ferumbras_ascendant/bosses/tarbaz.lua | 2 +- .../quests/ferumbras_ascendant/bosses/zamulosh.lua | 2 +- .../monster/quests/in_service_of_yalahar/inky.lua | 2 +- .../quests/in_service_of_yalahar/sharptooth.lua | 2 +- .../monster/reptiles/seacrest_serpent.lua | 2 +- .../monster/reptiles/young_sea_serpent.lua | 2 +- .../monster/undeads/betrayed_wraith.lua | 2 +- .../monster/undeads/blightwalker.lua | 7 +++---- .../monster/undeads/crypt_warrior.lua | 2 +- .../monster/undeads/falcon_knight.lua | 2 +- .../monster/undeads/falcon_paladin.lua | 2 +- .../monster/undeads/hand_of_cursed_fate.lua | 4 ++-- .../monster/undeads/skeleton_elite_warrior.lua | 2 +- .../monster/undeads/undead_dragon.lua | 2 +- .../monster/undeads/undead_elite_gladiator.lua | 2 +- .../monster/vermins/cave_devourer.lua | 4 ++-- .../monster/vermins/chasm_spawn.lua | 4 ++-- data-otservbr-global/monster/vermins/deepworm.lua | 2 +- data-otservbr-global/monster/vermins/diremaw.lua | 2 +- data-otservbr-global/monster/vermins/drillworm.lua | 2 +- .../monster/vermins/tunnel_tyrant.lua | 4 ++-- ...d_,master_oberon.lua => grand_master_oberon.lua} | 0 66 files changed, 105 insertions(+), 119 deletions(-) rename data-otservbr-global/scripts/actions/bosses_levers/{grand_,master_oberon.lua => grand_master_oberon.lua} (100%) diff --git a/data-canary/monster/demons/fury.lua b/data-canary/monster/demons/fury.lua index 3835050ce67..a01553afeed 100644 --- a/data-canary/monster/demons/fury.lua +++ b/data-canary/monster/demons/fury.lua @@ -125,7 +125,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 30 }, + { type = COMBAT_ICEDAMAGE, percent = 5 }, { type = COMBAT_HOLYDAMAGE, percent = 30 }, { type = COMBAT_DEATHDAMAGE, percent = -10 }, } diff --git a/data-canary/monster/demons/juggernaut.lua b/data-canary/monster/demons/juggernaut.lua index 7b3e3d1795b..704ce847f13 100644 --- a/data-canary/monster/demons/juggernaut.lua +++ b/data-canary/monster/demons/juggernaut.lua @@ -27,8 +27,8 @@ monster.Bestiary = { The Blood Halls, The Vats, The Hive, The Shadow Nexus, a room deep in Formorgar Mines, Roshamuul Prison, Oramond Dungeon, Grounds of Destruction.", } -monster.health = 20000 -monster.maxHealth = 20000 +monster.health = 18000 +monster.maxHealth = 18000 monster.race = "blood" monster.corpse = 6335 monster.speed = 170 diff --git a/data-otservbr-global/monster/aquatics/quara_constrictor.lua b/data-otservbr-global/monster/aquatics/quara_constrictor.lua index 02b4877620e..c04460f1f50 100644 --- a/data-otservbr-global/monster/aquatics/quara_constrictor.lua +++ b/data-otservbr-global/monster/aquatics/quara_constrictor.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Quara Constrictor") local monster = {} monster.description = "a quara constrictor" -monster.experience = 250 +monster.experience = 380 monster.outfit = { lookType = 46, lookHead = 0, diff --git a/data-otservbr-global/monster/aquatics/quara_hydromancer.lua b/data-otservbr-global/monster/aquatics/quara_hydromancer.lua index 4129dcfe81c..07c3ffbfda3 100644 --- a/data-otservbr-global/monster/aquatics/quara_hydromancer.lua +++ b/data-otservbr-global/monster/aquatics/quara_hydromancer.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Quara Hydromancer") local monster = {} monster.description = "a quara hydromancer" -monster.experience = 800 +monster.experience = 950 monster.outfit = { lookType = 47, lookHead = 0, diff --git a/data-otservbr-global/monster/aquatics/quara_mantassin.lua b/data-otservbr-global/monster/aquatics/quara_mantassin.lua index 53594881d50..3e857cab7f2 100644 --- a/data-otservbr-global/monster/aquatics/quara_mantassin.lua +++ b/data-otservbr-global/monster/aquatics/quara_mantassin.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Quara Mantassin") local monster = {} monster.description = "a quara mantassin" -monster.experience = 400 +monster.experience = 600 monster.outfit = { lookType = 72, lookHead = 0, diff --git a/data-otservbr-global/monster/aquatics/quara_pincher.lua b/data-otservbr-global/monster/aquatics/quara_pincher.lua index 200aed87628..09fea436314 100644 --- a/data-otservbr-global/monster/aquatics/quara_pincher.lua +++ b/data-otservbr-global/monster/aquatics/quara_pincher.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Quara Pincher") local monster = {} monster.description = "a quara pincher" -monster.experience = 1200 +monster.experience = 1500 monster.outfit = { lookType = 77, lookHead = 0, diff --git a/data-otservbr-global/monster/aquatics/quara_predator.lua b/data-otservbr-global/monster/aquatics/quara_predator.lua index e513aa5712c..b12719e26f8 100644 --- a/data-otservbr-global/monster/aquatics/quara_predator.lua +++ b/data-otservbr-global/monster/aquatics/quara_predator.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Quara Predator") local monster = {} monster.description = "a quara predator" -monster.experience = 1600 +monster.experience = 1850 monster.outfit = { lookType = 20, lookHead = 0, diff --git a/data-otservbr-global/monster/bosses/splasher.lua b/data-otservbr-global/monster/bosses/splasher.lua index 60b89710c4f..426d3be3c26 100644 --- a/data-otservbr-global/monster/bosses/splasher.lua +++ b/data-otservbr-global/monster/bosses/splasher.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Splasher") local monster = {} monster.description = "Splasher" -monster.experience = 500 +monster.experience = 1500 monster.outfit = { lookType = 47, lookHead = 0, diff --git a/data-otservbr-global/monster/constructs/clay_guardian.lua b/data-otservbr-global/monster/constructs/clay_guardian.lua index 804d671bdf9..fb28abe50c3 100644 --- a/data-otservbr-global/monster/constructs/clay_guardian.lua +++ b/data-otservbr-global/monster/constructs/clay_guardian.lua @@ -107,7 +107,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 35 }, + { type = COMBAT_ICEDAMAGE, percent = 20 }, { type = COMBAT_HOLYDAMAGE, percent = 0 }, { type = COMBAT_DEATHDAMAGE, percent = 40 }, } diff --git a/data-otservbr-global/monster/constructs/infected_weeper.lua b/data-otservbr-global/monster/constructs/infected_weeper.lua index e302618f3eb..2b7d97f0479 100644 --- a/data-otservbr-global/monster/constructs/infected_weeper.lua +++ b/data-otservbr-global/monster/constructs/infected_weeper.lua @@ -105,7 +105,7 @@ monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 50 }, { type = COMBAT_ENERGYDAMAGE, percent = 25 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, - { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = -100 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/constructs/lava_golem.lua b/data-otservbr-global/monster/constructs/lava_golem.lua index aed9ad864c0..5c3f695cf32 100644 --- a/data-otservbr-global/monster/constructs/lava_golem.lua +++ b/data-otservbr-global/monster/constructs/lava_golem.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Lava Golem") local monster = {} monster.description = "a lava golem" -monster.experience = 6200 +monster.experience = 7900 monster.outfit = { lookType = 491, lookHead = 0, @@ -109,7 +109,6 @@ monster.loot = { monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -400 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_FIREDAMAGE, minDamage = -350, maxDamage = -700, length = 8, spread = 0, effect = CONST_ME_FIREATTACK, target = false }, - { name = "combat", interval = 2000, chance = 10, type = COMBAT_MANADRAIN, minDamage = -600, maxDamage = -1300, length = 8, spread = 3, effect = CONST_ME_MORTAREA, target = false }, { name = "lava golem soulfire", interval = 2000, chance = 15, target = false }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_FIREDAMAGE, minDamage = -220, maxDamage = -350, radius = 4, effect = CONST_ME_FIREAREA, target = true }, { name = "speed", interval = 2000, chance = 10, speedChange = -800, length = 5, spread = 3, effect = CONST_ME_BLOCKHIT, target = false, duration = 30000 }, diff --git a/data-otservbr-global/monster/constructs/magma_crawler.lua b/data-otservbr-global/monster/constructs/magma_crawler.lua index 39c58ab8838..bf5f7ac4feb 100644 --- a/data-otservbr-global/monster/constructs/magma_crawler.lua +++ b/data-otservbr-global/monster/constructs/magma_crawler.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Magma Crawler") local monster = {} monster.description = "a magma crawler" -monster.experience = 2700 +monster.experience = 3900 monster.outfit = { lookType = 492, lookHead = 0, @@ -35,7 +35,7 @@ monster.manaCost = 0 monster.changeTarget = { interval = 4000, - chance = 10, + chance = 5, } monster.strategiesTarget = { @@ -118,7 +118,7 @@ monster.defenses = { defense = 45, armor = 84, mitigation = 2.51, - { name = "invisible", interval = 2000, chance = 10, effect = CONST_ME_MAGIC_BLUE }, + { name = "invisible", interval = 2000, chance = 5, effect = CONST_ME_MAGIC_BLUE }, } monster.elements = { @@ -129,7 +129,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 10 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, { type = COMBAT_HOLYDAMAGE, percent = 0 }, { type = COMBAT_DEATHDAMAGE, percent = 25 }, } diff --git a/data-otservbr-global/monster/constructs/orewalker.lua b/data-otservbr-global/monster/constructs/orewalker.lua index 767b8a049ae..3e1dc4deedd 100644 --- a/data-otservbr-global/monster/constructs/orewalker.lua +++ b/data-otservbr-global/monster/constructs/orewalker.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Orewalker") local monster = {} monster.description = "an orewalker" -monster.experience = 4800 +monster.experience = 5900 monster.outfit = { lookType = 490, lookHead = 0, @@ -112,7 +112,6 @@ monster.attacks = { { name = "combat", interval = 2000, chance = 10, type = COMBAT_PHYSICALDAMAGE, minDamage = 0, maxDamage = -1500, length = 6, spread = 3, effect = CONST_ME_GROUNDSHAKER, target = false }, -- poison { name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -800, maxDamage = -1080, radius = 3, shootEffect = CONST_ANI_SMALLEARTH, effect = CONST_ME_SMALLPLANTS, target = true }, - { name = "drunk", interval = 2000, chance = 15, radius = 4, effect = CONST_ME_SOUND_PURPLE, target = false, duration = 6000 }, { name = "speed", interval = 2000, chance = 15, speedChange = -800, radius = 2, effect = CONST_ME_MAGIC_RED, target = false, duration = 20000 }, } diff --git a/data-otservbr-global/monster/constructs/stone_devourer.lua b/data-otservbr-global/monster/constructs/stone_devourer.lua index 5a9174c3129..39c85402870 100644 --- a/data-otservbr-global/monster/constructs/stone_devourer.lua +++ b/data-otservbr-global/monster/constructs/stone_devourer.lua @@ -118,7 +118,7 @@ monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 10 }, { type = COMBAT_ENERGYDAMAGE, percent = 30 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, - { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = -5 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/constructs/weeper.lua b/data-otservbr-global/monster/constructs/weeper.lua index 75a8d7ebb42..cfc7c6b0d68 100644 --- a/data-otservbr-global/monster/constructs/weeper.lua +++ b/data-otservbr-global/monster/constructs/weeper.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Weeper") local monster = {} monster.description = "a weeper" -monster.experience = 4800 +monster.experience = 5800 monster.outfit = { lookType = 489, lookHead = 0, @@ -55,7 +55,7 @@ monster.flags = { canPushCreatures = true, staticAttackChance = 70, targetDistance = 1, - runHealth = 570, + runHealth = 0, healthHidden = false, isBlockable = false, canWalkOnEnergy = false, @@ -101,7 +101,7 @@ monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -450 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_FIREDAMAGE, minDamage = -400, maxDamage = -1000, length = 8, spread = 0, effect = CONST_ME_FIREATTACK, target = false }, { name = "combat", interval = 3000, chance = 100, type = COMBAT_FIREDAMAGE, minDamage = -80, maxDamage = -250, radius = 3, effect = CONST_ME_HITBYFIRE, target = false }, - { name = "speed", interval = 2000, chance = 10, speedChange = -800, length = 5, spread = 0, effect = CONST_ME_BLOCKHIT, target = false, duration = 30000 }, + { name = "speed", interval = 2000, chance = 10, speedChange = -600, length = 5, spread = 0, effect = CONST_ME_BLOCKHIT, target = false, duration = 30000 }, } monster.defenses = { diff --git a/data-otservbr-global/monster/demons/hellfire_fighter.lua b/data-otservbr-global/monster/demons/hellfire_fighter.lua index 6a90b5af06d..2ae5b00303a 100644 --- a/data-otservbr-global/monster/demons/hellfire_fighter.lua +++ b/data-otservbr-global/monster/demons/hellfire_fighter.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Hellfire Fighter") local monster = {} monster.description = "a hellfire fighter" -monster.experience = 3400 +monster.experience = 3800 monster.outfit = { lookType = 243, lookHead = 0, diff --git a/data-otservbr-global/monster/elementals/cliff_strider.lua b/data-otservbr-global/monster/elementals/cliff_strider.lua index 2690f356f23..2e143d42796 100644 --- a/data-otservbr-global/monster/elementals/cliff_strider.lua +++ b/data-otservbr-global/monster/elementals/cliff_strider.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Cliff Strider") local monster = {} monster.description = "a cliff strider" -monster.experience = 5700 +monster.experience = 7100 monster.outfit = { lookType = 497, lookHead = 0, @@ -119,7 +119,7 @@ monster.attacks = { { name = "cliff strider skill reducer", interval = 2000, chance = 10, target = false }, { name = "cliff strider electrify", interval = 2000, chance = 15, range = 1, target = false }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_PHYSICALDAMAGE, minDamage = 0, maxDamage = -1000, length = 6, spread = 0, effect = CONST_ME_GROUNDSHAKER, target = false }, - { name = "combat", interval = 2000, chance = 15, type = COMBAT_MANADRAIN, minDamage = -100, maxDamage = -300, radius = 4, effect = CONST_ME_YELLOWENERGY, target = false }, + { name = "combat", interval = 2000, chance = 10, type = COMBAT_MANADRAIN, minDamage = -100, maxDamage = -300, radius = 4, effect = CONST_ME_YELLOWENERGY, target = false }, } monster.defenses = { @@ -130,7 +130,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 10 }, - { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 5 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 20 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, diff --git a/data-otservbr-global/monster/elementals/earth_elemental.lua b/data-otservbr-global/monster/elementals/earth_elemental.lua index f71d6a7964d..4c3b3e11aa3 100644 --- a/data-otservbr-global/monster/elementals/earth_elemental.lua +++ b/data-otservbr-global/monster/elementals/earth_elemental.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Earth Elemental") local monster = {} monster.description = "an earth elemental" -monster.experience = 450 +monster.experience = 550 monster.outfit = { lookType = 301, lookHead = 0, @@ -117,7 +117,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 85 }, + { type = COMBAT_ICEDAMAGE, percent = 5 }, { type = COMBAT_HOLYDAMAGE, percent = 50 }, { type = COMBAT_DEATHDAMAGE, percent = 40 }, } diff --git a/data-otservbr-global/monster/elementals/high_voltage_elemental.lua b/data-otservbr-global/monster/elementals/high_voltage_elemental.lua index ca99e57527e..3d6806a707b 100644 --- a/data-otservbr-global/monster/elementals/high_voltage_elemental.lua +++ b/data-otservbr-global/monster/elementals/high_voltage_elemental.lua @@ -102,7 +102,7 @@ monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 35 }, { type = COMBAT_ENERGYDAMAGE, percent = 100 }, { type = COMBAT_EARTHDAMAGE, percent = -15 }, - { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = -100 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/elementals/ironblight.lua b/data-otservbr-global/monster/elementals/ironblight.lua index 593069318ed..7cb7c7c58fc 100644 --- a/data-otservbr-global/monster/elementals/ironblight.lua +++ b/data-otservbr-global/monster/elementals/ironblight.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Ironblight") local monster = {} monster.description = "an ironblight" -monster.experience = 4400 +monster.experience = 5400 monster.outfit = { lookType = 498, lookHead = 0, diff --git a/data-otservbr-global/monster/elementals/massive_earth_elemental.lua b/data-otservbr-global/monster/elementals/massive_earth_elemental.lua index e894319b6ec..1b131e7c7ae 100644 --- a/data-otservbr-global/monster/elementals/massive_earth_elemental.lua +++ b/data-otservbr-global/monster/elementals/massive_earth_elemental.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Massive Earth Elemental") local monster = {} monster.description = "a massive earth elemental" -monster.experience = 950 +monster.experience = 1100 monster.outfit = { lookType = 285, lookHead = 0, @@ -119,7 +119,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 100 }, + { type = COMBAT_ICEDAMAGE, percent = 15 }, { type = COMBAT_HOLYDAMAGE, percent = 50 }, { type = COMBAT_DEATHDAMAGE, percent = 45 }, } diff --git a/data-otservbr-global/monster/elementals/sulphur_spouter.lua b/data-otservbr-global/monster/elementals/sulphur_spouter.lua index 6f574cc0a07..79ebcf8db4b 100644 --- a/data-otservbr-global/monster/elementals/sulphur_spouter.lua +++ b/data-otservbr-global/monster/elementals/sulphur_spouter.lua @@ -105,7 +105,7 @@ monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, { type = COMBAT_ENERGYDAMAGE, percent = 0 }, { type = COMBAT_EARTHDAMAGE, percent = 0 }, - { type = COMBAT_FIREDAMAGE, percent = 100 }, + { type = COMBAT_FIREDAMAGE, percent = 25 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/humanoids/lost_basher.lua b/data-otservbr-global/monster/humanoids/lost_basher.lua index e19aef97f78..f8866bdd177 100644 --- a/data-otservbr-global/monster/humanoids/lost_basher.lua +++ b/data-otservbr-global/monster/humanoids/lost_basher.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Lost Basher") local monster = {} monster.description = "a lost basher" -monster.experience = 1800 +monster.experience = 2300 monster.outfit = { lookType = 538, lookHead = 0, @@ -61,7 +61,7 @@ monster.flags = { healthHidden = false, isBlockable = false, canWalkOnEnergy = false, - canWalkOnFire = false, + canWalkOnFire = true, canWalkOnPoison = true, } @@ -126,7 +126,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 20 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, { type = COMBAT_HOLYDAMAGE, percent = 0 }, { type = COMBAT_DEATHDAMAGE, percent = 15 }, } diff --git a/data-otservbr-global/monster/humanoids/lost_berserker.lua b/data-otservbr-global/monster/humanoids/lost_berserker.lua index cd48787df95..cbc7012ff95 100644 --- a/data-otservbr-global/monster/humanoids/lost_berserker.lua +++ b/data-otservbr-global/monster/humanoids/lost_berserker.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Lost Berserker") local monster = {} monster.description = "a lost berserker" -monster.experience = 4400 +monster.experience = 4800 monster.outfit = { lookType = 496, lookHead = 0, @@ -111,27 +111,25 @@ monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -501 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_PHYSICALDAMAGE, minDamage = 0, maxDamage = -300, range = 7, shootEffect = CONST_ANI_WHIRLWINDAXE, target = false }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_PHYSICALDAMAGE, minDamage = 0, maxDamage = -250, range = 7, radius = 3, shootEffect = CONST_ANI_EXPLOSION, effect = CONST_ME_EXPLOSIONAREA, target = true }, - { name = "combat", interval = 2000, chance = 10, type = COMBAT_MANADRAIN, minDamage = -150, maxDamage = -250, radius = 5, effect = CONST_ME_MAGIC_RED, target = false }, + { name = "combat", interval = 2000, chance = 10, type = COMBAT_MANADRAIN, minDamage = -50, maxDamage = -100, radius = 5, effect = CONST_ME_MAGIC_RED, target = false }, { name = "speed", interval = 2000, chance = 10, speedChange = -800, radius = 2, effect = CONST_ME_MAGIC_RED, target = false, duration = 20000 }, - { name = "drunk", interval = 2000, chance = 10, radius = 4, effect = CONST_ME_STUN, target = true, duration = 6000 }, } monster.defenses = { defense = 40, armor = 80, mitigation = 2.40, - { name = "invisible", interval = 2000, chance = 5, effect = CONST_ME_TELEPORT }, } monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 20 }, - { type = COMBAT_ENERGYDAMAGE, percent = 17 }, + { type = COMBAT_ENERGYDAMAGE, percent = 100 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 10 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 40 }, + { type = COMBAT_ICEDAMAGE, percent = 10 }, { type = COMBAT_HOLYDAMAGE, percent = 0 }, { type = COMBAT_DEATHDAMAGE, percent = 15 }, } @@ -139,7 +137,7 @@ monster.elements = { monster.immunities = { { type = "paralyze", condition = true }, { type = "outfit", condition = false }, - { type = "invisible", condition = true }, + { type = "invisible", condition = false }, { type = "bleed", condition = false }, } diff --git a/data-otservbr-global/monster/humanoids/lost_husher.lua b/data-otservbr-global/monster/humanoids/lost_husher.lua index d8167f9710d..419bae1ab96 100644 --- a/data-otservbr-global/monster/humanoids/lost_husher.lua +++ b/data-otservbr-global/monster/humanoids/lost_husher.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Lost Husher") local monster = {} monster.description = "a lost husher" -monster.experience = 1800 +monster.experience = 1100 monster.outfit = { lookType = 537, lookHead = 0, @@ -61,7 +61,7 @@ monster.flags = { healthHidden = false, isBlockable = false, canWalkOnEnergy = false, - canWalkOnFire = false, + canWalkOnFire = true, canWalkOnPoison = true, } @@ -103,7 +103,6 @@ monster.loot = { monster.attacks = { { name = "combat", interval = 2000, chance = 10, type = COMBAT_DEATHDAMAGE, minDamage = -150, maxDamage = -300, length = 6, spread = 0, effect = CONST_ME_BLACKSMOKE, target = false }, - { name = "combat", interval = 2000, chance = 10, type = COMBAT_MANADRAIN, minDamage = -150, maxDamage = -250, radius = 5, effect = CONST_ME_BLACKSMOKE, target = false }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_DEATHDAMAGE, minDamage = -150, maxDamage = -200, range = 7, shootEffect = CONST_ANI_SUDDENDEATH, effect = CONST_ME_MORTAREA, target = false }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_EARTHDAMAGE, minDamage = -150, maxDamage = -250, range = 7, radius = 2, shootEffect = CONST_ANI_SMALLEARTH, effect = CONST_ME_MAGIC_GREEN, target = true }, { name = "drunk", interval = 2000, chance = 10, radius = 4, effect = CONST_ME_SOUND_RED, target = false, duration = 6000 }, @@ -125,7 +124,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 15 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, { type = COMBAT_HOLYDAMAGE, percent = -10 }, { type = COMBAT_DEATHDAMAGE, percent = 20 }, } @@ -133,7 +132,7 @@ monster.elements = { monster.immunities = { { type = "paralyze", condition = true }, { type = "outfit", condition = false }, - { type = "invisible", condition = true }, + { type = "invisible", condition = false }, { type = "bleed", condition = false }, } diff --git a/data-otservbr-global/monster/humanoids/lost_thrower.lua b/data-otservbr-global/monster/humanoids/lost_thrower.lua index c2a87f0d551..21a14bce085 100644 --- a/data-otservbr-global/monster/humanoids/lost_thrower.lua +++ b/data-otservbr-global/monster/humanoids/lost_thrower.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Lost Thrower") local monster = {} monster.description = "a lost thrower" -monster.experience = 1200 +monster.experience = 1500 monster.outfit = { lookType = 539, lookHead = 0, @@ -61,7 +61,7 @@ monster.flags = { healthHidden = false, isBlockable = false, canWalkOnEnergy = false, - canWalkOnFire = false, + canWalkOnFire = true, canWalkOnPoison = true, } @@ -117,7 +117,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 15 }, + { type = COMBAT_ICEDAMAGE, percent = -5 }, { type = COMBAT_HOLYDAMAGE, percent = 0 }, { type = COMBAT_DEATHDAMAGE, percent = 10 }, } diff --git a/data-otservbr-global/monster/magicals/armadile.lua b/data-otservbr-global/monster/magicals/armadile.lua index beca89510f4..98665845d28 100644 --- a/data-otservbr-global/monster/magicals/armadile.lua +++ b/data-otservbr-global/monster/magicals/armadile.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Armadile") local monster = {} monster.description = "an armadile" -monster.experience = 2900 +monster.experience = 3200 monster.outfit = { lookType = 487, lookHead = 0, @@ -56,8 +56,8 @@ monster.flags = { canPushItems = false, canPushCreatures = true, staticAttackChance = 90, - targetDistance = 4, - runHealth = 300, + targetDistance = 1, + runHealth = 0, healthHidden = false, isBlockable = false, canWalkOnEnergy = false, @@ -102,9 +102,7 @@ monster.loot = { monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -150 }, - { name = "drunk", interval = 2000, chance = 15, radius = 4, effect = CONST_ME_FIREAREA, target = true, duration = 5000 }, - { name = "combat", interval = 2000, chance = 15, type = COMBAT_MANADRAIN, minDamage = -430, maxDamage = -550, range = 7, effect = CONST_ME_MAGIC_BLUE, target = false }, - -- poison + { name = "drunk", interval = 2000, chance = 10, radius = 4, effect = CONST_ME_FIREAREA, target = true, duration = 5000 }, { name = "condition", type = CONDITION_POISON, interval = 2000, chance = 15, minDamage = -200, maxDamage = -400, radius = 4, effect = CONST_ME_POISONAREA, target = false }, } @@ -112,14 +110,13 @@ monster.defenses = { defense = 25, armor = 66, mitigation = 1.96, - { name = "invisible", interval = 2000, chance = 15, effect = CONST_ME_MAGIC_RED }, } monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 5 }, { type = COMBAT_ENERGYDAMAGE, percent = 15 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, - { type = COMBAT_FIREDAMAGE, percent = 20 }, + { type = COMBAT_FIREDAMAGE, percent = 0 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/magicals/choking_fear.lua b/data-otservbr-global/monster/magicals/choking_fear.lua index 16361bab0e9..604ca5cdaa6 100644 --- a/data-otservbr-global/monster/magicals/choking_fear.lua +++ b/data-otservbr-global/monster/magicals/choking_fear.lua @@ -124,7 +124,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 10 }, - { type = COMBAT_ENERGYDAMAGE, percent = 15 }, + { type = COMBAT_ENERGYDAMAGE, percent = 2 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 100 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, diff --git a/data-otservbr-global/monster/magicals/phantasm.lua b/data-otservbr-global/monster/magicals/phantasm.lua index 9dc266f8bb3..36c0baed405 100644 --- a/data-otservbr-global/monster/magicals/phantasm.lua +++ b/data-otservbr-global/monster/magicals/phantasm.lua @@ -70,7 +70,7 @@ monster.light = { monster.summon = { maxSummons = 4, summons = { - { name = "Phantasm Summon", chance = 20, interval = 2000, count = 4 }, + { name = "Phantasm Summon", chance = 35, interval = 2000, count = 4 }, }, } diff --git a/data-otservbr-global/monster/magicals/retching_horror.lua b/data-otservbr-global/monster/magicals/retching_horror.lua index a6814343eaf..0479a7cb368 100644 --- a/data-otservbr-global/monster/magicals/retching_horror.lua +++ b/data-otservbr-global/monster/magicals/retching_horror.lua @@ -113,7 +113,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 5 }, - { type = COMBAT_ENERGYDAMAGE, percent = 10 }, + { type = COMBAT_ENERGYDAMAGE, percent = -3 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 85 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, diff --git a/data-otservbr-global/monster/mammals/mutated_bat.lua b/data-otservbr-global/monster/mammals/mutated_bat.lua index 211ca62d2ad..dfea480341b 100644 --- a/data-otservbr-global/monster/mammals/mutated_bat.lua +++ b/data-otservbr-global/monster/mammals/mutated_bat.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Mutated Bat") local monster = {} monster.description = "a mutated bat" -monster.experience = 615 +monster.experience = 750 monster.outfit = { lookType = 307, lookHead = 0, diff --git a/data-otservbr-global/monster/plants/hideous_fungus.lua b/data-otservbr-global/monster/plants/hideous_fungus.lua index a80ba080fd7..275adb03b2f 100644 --- a/data-otservbr-global/monster/plants/hideous_fungus.lua +++ b/data-otservbr-global/monster/plants/hideous_fungus.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Hideous Fungus") local monster = {} monster.description = "a hideous fungus" -monster.experience = 2900 +monster.experience = 3700 monster.outfit = { lookType = 499, lookHead = 0, @@ -57,7 +57,7 @@ monster.flags = { canPushCreatures = true, staticAttackChance = 90, targetDistance = 4, - runHealth = 275, + runHealth = 0, healthHidden = false, isBlockable = false, canWalkOnEnergy = true, @@ -71,9 +71,9 @@ monster.light = { } monster.summon = { - maxSummons = 2, + maxSummons = 1, summons = { - { name = "humorless fungus", chance = 10, interval = 2000, count = 2 }, + { name = "humorless fungus", chance = 10, interval = 2000, count = 1 }, }, } @@ -110,7 +110,6 @@ monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -450 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_EARTHDAMAGE, minDamage = -250, maxDamage = -430, range = 7, shootEffect = CONST_ANI_SMALLEARTH, effect = CONST_ME_SMALLPLANTS, target = false }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_ICEDAMAGE, minDamage = -250, maxDamage = -550, length = 8, spread = 0, shootEffect = CONST_ANI_SNOWBALL, effect = CONST_ME_ICEAREA, target = false }, - { name = "speed", interval = 2000, chance = 10, speedChange = -600, radius = 1, effect = CONST_ME_MAGIC_RED, target = true, duration = 60000 }, { name = "drunk", interval = 2000, chance = 10, range = 7, radius = 5, shootEffect = CONST_ANI_SMALLSTONE, effect = CONST_ME_STUN, target = true, duration = 4000 }, -- poison { name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -400, maxDamage = -640, range = 7, radius = 3, effect = CONST_ME_HITBYPOISON, target = false }, @@ -121,14 +120,14 @@ monster.defenses = { armor = 60, mitigation = 1.74, { name = "combat", interval = 2000, chance = 15, type = COMBAT_HEALING, minDamage = 275, maxDamage = 350, effect = CONST_ME_MAGIC_BLUE, target = false }, - { name = "invisible", interval = 2000, chance = 10, effect = CONST_ME_MAGIC_BLUE }, + { name = "invisible", interval = 2000, chance = 5, effect = CONST_ME_MAGIC_BLUE, duration = 2000 }, } monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, { type = COMBAT_ENERGYDAMAGE, percent = 15 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, - { type = COMBAT_FIREDAMAGE, percent = 5 }, + { type = COMBAT_FIREDAMAGE, percent = -5 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/plants/humongous_fungus.lua b/data-otservbr-global/monster/plants/humongous_fungus.lua index 942684e732c..09f301a6a59 100644 --- a/data-otservbr-global/monster/plants/humongous_fungus.lua +++ b/data-otservbr-global/monster/plants/humongous_fungus.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Humongous Fungus") local monster = {} monster.description = "a humongous fungus" -monster.experience = 2600 +monster.experience = 2900 monster.outfit = { lookType = 488, lookHead = 0, @@ -104,7 +104,7 @@ monster.loot = { monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -330 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_EARTHDAMAGE, minDamage = -180, maxDamage = -350, range = 7, shootEffect = CONST_ANI_SMALLEARTH, effect = CONST_ME_SMALLPLANTS, target = false }, - { name = "poisonfield", interval = 2000, chance = 20, radius = 4, target = false }, + { name = "poisonfield", interval = 2000, chance = 10, radius = 4, target = false }, -- poison { name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -500, maxDamage = -1000, length = 8, spread = 0, effect = CONST_ME_GREEN_RINGS, target = false }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_LIFEDRAIN, minDamage = -130, maxDamage = -260, length = 5, spread = 0, effect = CONST_ME_MAGIC_RED, target = false }, @@ -117,14 +117,13 @@ monster.defenses = { armor = 70, mitigation = 2.02, { name = "combat", interval = 2000, chance = 10, type = COMBAT_HEALING, minDamage = 225, maxDamage = 380, effect = CONST_ME_MAGIC_BLUE, target = false }, - { name = "invisible", interval = 2000, chance = 15, effect = CONST_ME_MAGIC_BLUE }, } monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, { type = COMBAT_ENERGYDAMAGE, percent = 15 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, - { type = COMBAT_FIREDAMAGE, percent = 5 }, + { type = COMBAT_FIREDAMAGE, percent = -10 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, diff --git a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua index 24c993fda5b..1ca0ff1ca75 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/abyssador.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Abyssador") local monster = {} monster.description = "Abyssador" -monster.experience = 50000 +monster.experience = 400000 monster.outfit = { lookType = 495, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua index cd287d83709..8d410c85d26 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/bosses/gnomevil.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Gnomevil") local monster = {} monster.description = "Gnomevil" -monster.experience = 45000 +monster.experience = 400000 monster.outfit = { lookType = 504, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/bigfoots_burden/humorless_fungus.lua b/data-otservbr-global/monster/quests/bigfoots_burden/humorless_fungus.lua index 19ab3230231..ead6b096fbf 100644 --- a/data-otservbr-global/monster/quests/bigfoots_burden/humorless_fungus.lua +++ b/data-otservbr-global/monster/quests/bigfoots_burden/humorless_fungus.lua @@ -13,8 +13,8 @@ monster.outfit = { lookMount = 0, } -monster.health = 2500 -monster.maxHealth = 2500 +monster.health = 1600 +monster.maxHealth = 1600 monster.race = "venom" monster.corpse = 16083 monster.speed = 115 @@ -70,17 +70,14 @@ monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -475 }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_EARTHDAMAGE, minDamage = -40, maxDamage = -197, range = 7, shootEffect = CONST_ANI_SMALLEARTH, effect = CONST_ME_SMALLPLANTS, target = true }, { name = "combat", interval = 2000, chance = 10, type = COMBAT_ICEDAMAGE, minDamage = 0, maxDamage = -525, range = 7, shootEffect = CONST_ANI_SNOWBALL, effect = CONST_ME_ICEAREA, target = true }, - -- poison { name = "condition", type = CONDITION_POISON, interval = 2000, chance = 10, minDamage = -400, maxDamage = -640, range = 7, radius = 3, effect = CONST_ME_HITBYPOISON, target = false }, - { name = "drunk", interval = 2000, chance = 10, range = 7, radius = 4, effect = CONST_ME_STUN, target = true, duration = 4000 }, } monster.defenses = { defense = 0, armor = 0, - -- mitigation = ???, { name = "combat", interval = 2000, chance = 5, type = COMBAT_HEALING, minDamage = 0, maxDamage = 230, effect = CONST_ME_MAGIC_BLUE, target = false }, - { name = "invisible", interval = 2000, chance = 10, effect = CONST_ME_MAGIC_BLUE }, + { name = "invisible", interval = 2000, chance = 5, effect = CONST_ME_MAGIC_BLUE }, } monster.elements = { 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 d611e78d84b..17cb6520d29 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 @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("The Count of the Core") local monster = {} monster.description = "The Count Of The Core" -monster.experience = 40000 +monster.experience = 300000 monster.outfit = { lookType = 1046, lookHead = 0, 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 d654288c405..99053b93882 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 @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("The Duke of the Depths") local monster = {} monster.description = "The Duke Of The Depths" -monster.experience = 40000 +monster.experience = 300000 monster.outfit = { lookType = 1047, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua index 90b3124369a..7ad855bc88a 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Ferumbras Mortal Shell") local monster = {} monster.description = "Ferumbras Mortal Shell" -monster.experience = 500000 +monster.experience = 2000000 monster.outfit = { lookType = 229, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua index 0e0822e3d72..3f32bac95d4 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Mazoran") local monster = {} monster.description = "Mazoran" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 842, lookHead = 77, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua index 625f10cf7fc..364b4f864a8 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Plagirath") local monster = {} monster.description = "Plagirath" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 862, lookHead = 84, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua index 9701dc7d0f9..df016edfd84 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Ragiaz") local monster = {} monster.description = "Ragiaz" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 862, lookHead = 76, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua index 67d218c5ee0..066e22237c0 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Razzagorn") local monster = {} monster.description = "Razzagorn" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 842, lookHead = 78, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua index c0de2c0c362..72c908104af 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Shulgrax") local monster = {} monster.description = "Shulgrax" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 842, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua index 583167460e1..30b99353cdf 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Tarbaz") local monster = {} monster.description = "Tarbaz" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 842, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua index 5a441ff10f1..03fa92d3394 100644 --- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua +++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Zamulosh") local monster = {} monster.description = "Zamulosh" -monster.experience = 250000 +monster.experience = 500000 monster.outfit = { lookType = 862, lookHead = 16, diff --git a/data-otservbr-global/monster/quests/in_service_of_yalahar/inky.lua b/data-otservbr-global/monster/quests/in_service_of_yalahar/inky.lua index 49025f4c6c4..bbc58881ee4 100644 --- a/data-otservbr-global/monster/quests/in_service_of_yalahar/inky.lua +++ b/data-otservbr-global/monster/quests/in_service_of_yalahar/inky.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Inky") local monster = {} monster.description = "Inky" -monster.experience = 250 +monster.experience = 700 monster.outfit = { lookType = 46, lookHead = 0, diff --git a/data-otservbr-global/monster/quests/in_service_of_yalahar/sharptooth.lua b/data-otservbr-global/monster/quests/in_service_of_yalahar/sharptooth.lua index 583df08b8b5..0325642344c 100644 --- a/data-otservbr-global/monster/quests/in_service_of_yalahar/sharptooth.lua +++ b/data-otservbr-global/monster/quests/in_service_of_yalahar/sharptooth.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Sharptooth") local monster = {} monster.description = "Sharptooth" -monster.experience = 1600 +monster.experience = 3000 monster.outfit = { lookType = 20, lookHead = 0, diff --git a/data-otservbr-global/monster/reptiles/seacrest_serpent.lua b/data-otservbr-global/monster/reptiles/seacrest_serpent.lua index 9be39aaa571..04b7dba7416 100644 --- a/data-otservbr-global/monster/reptiles/seacrest_serpent.lua +++ b/data-otservbr-global/monster/reptiles/seacrest_serpent.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Seacrest Serpent") local monster = {} monster.description = "a seacrest serpent" -monster.experience = 2600 +monster.experience = 2900 monster.outfit = { lookType = 675, lookHead = 0, diff --git a/data-otservbr-global/monster/reptiles/young_sea_serpent.lua b/data-otservbr-global/monster/reptiles/young_sea_serpent.lua index 961ff8204c6..98e8744b7b1 100644 --- a/data-otservbr-global/monster/reptiles/young_sea_serpent.lua +++ b/data-otservbr-global/monster/reptiles/young_sea_serpent.lua @@ -108,7 +108,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = -20 }, { type = COMBAT_ENERGYDAMAGE, percent = -10 }, - { type = COMBAT_EARTHDAMAGE, percent = 100 }, + { type = COMBAT_EARTHDAMAGE, percent = -5 }, { type = COMBAT_FIREDAMAGE, percent = 30 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, diff --git a/data-otservbr-global/monster/undeads/betrayed_wraith.lua b/data-otservbr-global/monster/undeads/betrayed_wraith.lua index 0c0648acda5..201887a7712 100644 --- a/data-otservbr-global/monster/undeads/betrayed_wraith.lua +++ b/data-otservbr-global/monster/undeads/betrayed_wraith.lua @@ -112,7 +112,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, - { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 10 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 100 }, { type = COMBAT_LIFEDRAIN, percent = 100 }, diff --git a/data-otservbr-global/monster/undeads/blightwalker.lua b/data-otservbr-global/monster/undeads/blightwalker.lua index 28706adeb50..d900484b19f 100644 --- a/data-otservbr-global/monster/undeads/blightwalker.lua +++ b/data-otservbr-global/monster/undeads/blightwalker.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Blightwalker") local monster = {} monster.description = "a blightwalker" -monster.experience = 5850 +monster.experience = 6400 monster.outfit = { lookType = 246, lookHead = 0, @@ -108,9 +108,8 @@ monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -490 }, { name = "combat", interval = 2000, chance = 20, type = COMBAT_EARTHDAMAGE, minDamage = -220, maxDamage = -405, range = 7, radius = 1, shootEffect = CONST_ANI_POISON, target = true }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_LIFEDRAIN, minDamage = -65, maxDamage = -135, radius = 4, effect = CONST_ME_MAGIC_GREEN, target = false }, - { name = "drunk", interval = 2000, chance = 10, radius = 3, effect = CONST_ME_HITBYPOISON, target = false, duration = 5000 }, { name = "blightwalker curse", interval = 2000, chance = 15, target = false }, - { name = "speed", interval = 2000, chance = 15, speedChange = -300, range = 7, shootEffect = CONST_ANI_POISON, target = true, duration = 30000 }, + { name = "speed", interval = 2000, chance = 10, speedChange = -300, range = 7, shootEffect = CONST_ANI_POISON, target = true, duration = 15000 }, } monster.defenses = { @@ -127,7 +126,7 @@ monster.elements = { { type = COMBAT_LIFEDRAIN, percent = 0 }, { type = COMBAT_MANADRAIN, percent = 0 }, { type = COMBAT_DROWNDAMAGE, percent = 0 }, - { type = COMBAT_ICEDAMAGE, percent = 50 }, + { type = COMBAT_ICEDAMAGE, percent = 15 }, { type = COMBAT_HOLYDAMAGE, percent = -30 }, { type = COMBAT_DEATHDAMAGE, percent = 100 }, } diff --git a/data-otservbr-global/monster/undeads/crypt_warrior.lua b/data-otservbr-global/monster/undeads/crypt_warrior.lua index 5de0ab637ba..dad0cbe7529 100644 --- a/data-otservbr-global/monster/undeads/crypt_warrior.lua +++ b/data-otservbr-global/monster/undeads/crypt_warrior.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Crypt Warrior") local monster = {} monster.description = "a crypt warrior" -monster.experience = 4200 +monster.experience = 6050 monster.outfit = { lookType = 298, lookHead = 0, diff --git a/data-otservbr-global/monster/undeads/falcon_knight.lua b/data-otservbr-global/monster/undeads/falcon_knight.lua index 54a23130758..2e2ac28a1fe 100644 --- a/data-otservbr-global/monster/undeads/falcon_knight.lua +++ b/data-otservbr-global/monster/undeads/falcon_knight.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Falcon Knight") local monster = {} monster.description = "a falcon knight" -monster.experience = 5985 +monster.experience = 6300 monster.outfit = { lookType = 1071, lookHead = 57, diff --git a/data-otservbr-global/monster/undeads/falcon_paladin.lua b/data-otservbr-global/monster/undeads/falcon_paladin.lua index 799143fe943..cc6a41571e4 100644 --- a/data-otservbr-global/monster/undeads/falcon_paladin.lua +++ b/data-otservbr-global/monster/undeads/falcon_paladin.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Falcon Paladin") local monster = {} monster.description = "a falcon paladin" -monster.experience = 6544 +monster.experience = 6900 monster.outfit = { lookType = 1071, lookHead = 57, diff --git a/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua b/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua index b1f76414dd4..527d0708730 100644 --- a/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua +++ b/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua @@ -108,7 +108,7 @@ monster.loot = { monster.attacks = { { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -520, condition = { type = CONDITION_POISON, totalDamage = 380, interval = 4000 } }, - { name = "combat", interval = 2000, chance = 15, type = COMBAT_MANADRAIN, minDamage = 0, maxDamage = -920, range = 1, target = false }, + { name = "combat", interval = 2000, chance = 15, type = COMBAT_MANADRAIN, minDamage = 0, maxDamage = -620, range = 1, target = false }, { name = "drunk", interval = 2000, chance = 10, radius = 4, effect = CONST_ME_SMALLCLOUDS, target = false, duration = 3000 }, { name = "combat", interval = 2000, chance = 15, type = COMBAT_LIFEDRAIN, minDamage = -220, maxDamage = -880, range = 1, effect = CONST_ME_SMALLCLOUDS, target = false }, } @@ -124,7 +124,7 @@ monster.defenses = { monster.elements = { { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, - { type = COMBAT_ENERGYDAMAGE, percent = 100 }, + { type = COMBAT_ENERGYDAMAGE, percent = 5 }, { type = COMBAT_EARTHDAMAGE, percent = 100 }, { type = COMBAT_FIREDAMAGE, percent = 100 }, { type = COMBAT_LIFEDRAIN, percent = 0 }, diff --git a/data-otservbr-global/monster/undeads/skeleton_elite_warrior.lua b/data-otservbr-global/monster/undeads/skeleton_elite_warrior.lua index a0cc7545b99..25ebd9c1f6d 100644 --- a/data-otservbr-global/monster/undeads/skeleton_elite_warrior.lua +++ b/data-otservbr-global/monster/undeads/skeleton_elite_warrior.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Skeleton Elite Warrior") local monster = {} monster.description = "a skeleton elite warrior" -monster.experience = 4500 +monster.experience = 4800 monster.outfit = { lookType = 298, lookHead = 0, diff --git a/data-otservbr-global/monster/undeads/undead_dragon.lua b/data-otservbr-global/monster/undeads/undead_dragon.lua index 2ab63af8b77..b9039c5d914 100644 --- a/data-otservbr-global/monster/undeads/undead_dragon.lua +++ b/data-otservbr-global/monster/undeads/undead_dragon.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Undead Dragon") local monster = {} monster.description = "an undead dragon" -monster.experience = 7200 +monster.experience = 7500 monster.outfit = { lookType = 231, lookHead = 0, diff --git a/data-otservbr-global/monster/undeads/undead_elite_gladiator.lua b/data-otservbr-global/monster/undeads/undead_elite_gladiator.lua index 0f66c87cb21..10d1d5b08bc 100644 --- a/data-otservbr-global/monster/undeads/undead_elite_gladiator.lua +++ b/data-otservbr-global/monster/undeads/undead_elite_gladiator.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Undead Elite Gladiator") local monster = {} monster.description = "an undead elite gladiator" -monster.experience = 4740 +monster.experience = 5090 monster.outfit = { lookType = 306, lookHead = 0, diff --git a/data-otservbr-global/monster/vermins/cave_devourer.lua b/data-otservbr-global/monster/vermins/cave_devourer.lua index 1283ac20b81..17d89dfb176 100644 --- a/data-otservbr-global/monster/vermins/cave_devourer.lua +++ b/data-otservbr-global/monster/vermins/cave_devourer.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Cave Devourer") local monster = {} monster.description = "a cave devourer" -monster.experience = 2380 +monster.experience = 3380 monster.outfit = { lookType = 1036, lookHead = 0, @@ -88,7 +88,7 @@ monster.loot = { { name = "slime heart", chance = 13770, maxCount = 4 }, { name = "cave devourer legs", chance = 17160 }, { id = 3049, chance = 2540 }, -- stealth ring - { name = "suspicious device", chance = 420 }, + { name = "suspicious device", chance = 850 }, } monster.attacks = { diff --git a/data-otservbr-global/monster/vermins/chasm_spawn.lua b/data-otservbr-global/monster/vermins/chasm_spawn.lua index 0764367a1d0..9f27f57b006 100644 --- a/data-otservbr-global/monster/vermins/chasm_spawn.lua +++ b/data-otservbr-global/monster/vermins/chasm_spawn.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Chasm Spawn") local monster = {} monster.description = "a chasm spawn" -monster.experience = 2700 +monster.experience = 3600 monster.outfit = { lookType = 1037, lookHead = 0, @@ -89,7 +89,7 @@ monster.loot = { { name = "green crystal shard", chance = 7850 }, { name = "violet crystal shard", chance = 4690 }, { name = "mushroom backpack", chance = 610 }, - { name = "suspicious device", chance = 520 }, + { name = "suspicious device", chance = 850 }, } monster.attacks = { diff --git a/data-otservbr-global/monster/vermins/deepworm.lua b/data-otservbr-global/monster/vermins/deepworm.lua index 91b2ded8752..21775b2c673 100644 --- a/data-otservbr-global/monster/vermins/deepworm.lua +++ b/data-otservbr-global/monster/vermins/deepworm.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Deepworm") local monster = {} monster.description = "a deepworm" -monster.experience = 2300 +monster.experience = 2520 monster.outfit = { lookType = 1033, lookHead = 0, diff --git a/data-otservbr-global/monster/vermins/diremaw.lua b/data-otservbr-global/monster/vermins/diremaw.lua index b89c47c99e7..fd74c4e2be6 100644 --- a/data-otservbr-global/monster/vermins/diremaw.lua +++ b/data-otservbr-global/monster/vermins/diremaw.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Diremaw") local monster = {} monster.description = "a diremaw" -monster.experience = 2500 +monster.experience = 2770 monster.outfit = { lookType = 1034, lookHead = 0, diff --git a/data-otservbr-global/monster/vermins/drillworm.lua b/data-otservbr-global/monster/vermins/drillworm.lua index 3cf92fce18a..a435dc16ca3 100644 --- a/data-otservbr-global/monster/vermins/drillworm.lua +++ b/data-otservbr-global/monster/vermins/drillworm.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Drillworm") local monster = {} monster.description = "a drillworm" -monster.experience = 858 +monster.experience = 1200 monster.outfit = { lookType = 527, lookHead = 0, diff --git a/data-otservbr-global/monster/vermins/tunnel_tyrant.lua b/data-otservbr-global/monster/vermins/tunnel_tyrant.lua index f8e3b7bfb03..c2b8eb2df90 100644 --- a/data-otservbr-global/monster/vermins/tunnel_tyrant.lua +++ b/data-otservbr-global/monster/vermins/tunnel_tyrant.lua @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Tunnel Tyrant") local monster = {} monster.description = "a tunnel tyrant" -monster.experience = 3400 +monster.experience = 4420 monster.outfit = { lookType = 1035, lookHead = 0, @@ -87,7 +87,7 @@ monster.loot = { { name = "crystal mace", chance = 1580 }, { id = 23508, chance = 3010 }, -- energy vein { name = "crystalline armor", chance = 860 }, - { name = "suspicious device", chance = 1290 }, + { name = "suspicious device", chance = 1850 }, } monster.attacks = { diff --git a/data-otservbr-global/scripts/actions/bosses_levers/grand_,master_oberon.lua b/data-otservbr-global/scripts/actions/bosses_levers/grand_master_oberon.lua similarity index 100% rename from data-otservbr-global/scripts/actions/bosses_levers/grand_,master_oberon.lua rename to data-otservbr-global/scripts/actions/bosses_levers/grand_master_oberon.lua